LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   finding files n mins older or newer then a specific file (https://www.linuxquestions.org/questions/linux-newbie-8/finding-files-n-mins-older-or-newer-then-a-specific-file-929009/)

species3618 02-12-2012 03:50 PM

finding files n mins older or newer then a specific file
 
Hey!

I was wondering if it was possible to find files created, accessed or modified 30 mins before a specific file was created, access or modified using shell commands.

e.g

I find a file that was created on my system yesterday at 10am, I now want to find all files that were created between 9:30am and 10am, is this possible?

Thanks

chrism01 02-12-2012 05:30 PM

Well, this works for dates (days)
Code:

find . -mtime +1 -and -mtime -30 -print
so you should be able to use -mmin similarly. See http://linux.die.net/man/1/find 'Tests' section

Dark_Helmet 02-12-2012 05:35 PM

In a nutshell, yes. Though, the way you phrased your question leaves some ambiguity as to exactly what you want.

First, the find command can filter files based modification, status change, and access:
Code:

-amin n
-cmin n
-mmin n

The 'n' represents the minutes for the change. With '+n' meaning "greater than n minutes ago", with 'n' meaning "exactly equal to n minutes ago", and with '-n' meaning "less than n minutes ago".

Further, find allows you to combine the options using logical AND and OR conditions. A logical AND is applied to sequential options by default. So it is possible for you to do something such as:
Code:

-amin -31 -amin +1
Roughly translated: find a file accessed less than 31 minutes ago and also accessed greater than 1 minute ago.

The man page for find (man find) also states that these comparisons are based on the values from stat. You can run stat manually on a particular file:
Code:

stat somefilename
Beyond that, you can tell stat what specific information to print. Specifically, look at the "--printf" option. To display the number of seconds since the Epoch for that the file was accessed:
Code:

stat --printf="%X\n" somefilename
There are similar options for status change and modification time.

To tie it all together, you could write a script that:
1. Execute a stat on your reference file and stores the access, status change, and modification time for your reference file
2. Execute date with a date string to get the current number of seconds since the Epoch
3. Store for each access/status/modification time the from date minus the value for that particular time received from stat
4. Add an amount of seconds to each equal to the outer limit of your test (30 minutes in this case = 1800 seconds)
5. Convert the seconds into minutes by dividing with 60
6. Calculate your inner limit for each time (the original times returned by stat in this case), but converted to minutes
7. Construct your find command with those values. For instance:
Code:

find / -amin -<outer limit access> -amin +<inner limit access> -cmin -<outer limit status change> -cmin +<inner limit status change> -mmin -<outer limit modification> -mmin +<inner limit modification>
Where you substitute a calculated numeric value for each <outer...> and <inner...> reference.

The ambiguity I mentioned to begin with is because you don't specify whether you want to treat each specific time type (access, status, modification) separately (as I have done in the above example) or if you want to use the earliest value among the three.

EDIT:
A bash script doing what I described above might be:
Code:

#!/bin/bash

findPath=/      # Top-level directory for the find path to work from
innerOffset=0    # Adjustment (in seconds) to inner limit
outerOffset=1800 # Adjustment (in seconds) to outer limit

# Check that one filename was provided
if [ $# -ne 1 ] ; then
  echo "This script takes one and only one filename as a reference file."
  exit 1
fi

# Check that we have read access to the file
if [ ! -r "${1}" ] ; then
  echo "\"${1}\" is not a readable file. Exiting."
  exit 2
fi

# Get the different times associated with the file (in seconds since Epoch)
read accessTime modificationTime changeTime < <(/usr/bin/stat --printf="%X %Y %Z" "${1}")

# Get the current time (in seconds since Epoch)
currentTime=$( date '+%s' )

# Calculate inner limits and convert to minutes
((inner_amin=(currentTime-accessTime+innerOffset)/60))
((inner_cmin=(currentTime-changeTime+innerOffset)/60))
((inner_mmin=(currentTime-modificationTime+innerOffset)/60))

# Calculate outer limits and convert to minutes
((outer_amin=(currentTime-accessTime+outerOffset)/60))
((outer_cmin=(currentTime-changeTime+outerOffset)/60))
((outer_mmin=(currentTime-modificationTime+outerOffset)/60))

# Echo the equivalent find command
echo "find \"${findPath}\" -amin -${outer_amin} -amin +${inner_amin} -cmin -${outer_cmin} -cmin +${inner_cmin} -mmin -${outer_mmin} -mmin +${inner_cmin}"

Run the script with the name of a reference file as an argument. Adjust the variables at the top of the script as needed (or code up your own command line switches/arguments). Keep in mind that the +/- numeric values are strictly greater-than or strictly less-than operations (and will not include equal-to for files that reside on the precise value of the test).

Lastly, it will only print the rough equivalent of a find command for you--not execute it. The script could be modified to do so, but I have no idea what other restrictions or tests you would want to add.

David the H. 02-13-2012 10:06 AM

Here are a couple of useful links about using find:
http://mywiki.wooledge.org/UsingFind
http://www.grymoire.com/Unix/Find.html


All times are GMT -5. The time now is 04:36 AM.