Find files which are created a certain time after or before a particular file was created

I need a shell script which finds files which are created 1 hour before or 1 hour after a particular file (test.txt) was created.

If I go with find -newer, that means I’d have to create a temporary file, use touch to change the time on that 1 hour before the creation time of the test.txt file, and then use -newer tempFile to find the files which are newer than the tempFile, ultimately finding the files which are created 1 hour before the test.txt file. Then I have to go back through that process to find those an hour or more older than the file I’m interested in. That seems like a lot of extra work to go through to answer a simple question.

I also see find -mmin, but I worry that it’s an extension to POSIX find.

Any other suggestions?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Try the following shell code:

file=</PATH/TO/FILE>
date=$(perl -le '$s = (stat($ARGV[0]))[9]; print $s;' "$file")
now=$(date +%s)
seconds=$((now - date))
mins=$((seconds / 60))
find . -mmin -$((mins + 60 )) -mmin +$((mins - 60)) -print

Solution 2

Another complicated option:

  1. get test.txt‘s modification time (mtime)
  2. calculate "before delta" = now + hour - mtime (assuming mtime is in the past)
  3. calculate "after delta" = now - hour - mtime if now - mtime > hour else 0
  4. run find -type f -mmin -"before delta" -mmin +"after delta"

It finds all files that are modified less than “before delta” minutes ago and greater than “after delta” minutes ago i.e., +/- hour around test.txt‘s modification time.

It might be simpler to understand if you draw now, mtime, "before", "after" times on a line.

date command allows to get now and mtime.

As a one-liner:

$ find -type f -newermt "$(date -r $file) -1 hour" -a \
            \! -newermt "$(date -r $file) +1 hour"

Solution 3

You could do:

d=$(TZ=UTC0 date -r test.txt +%Y%m%d%H%M.%S)

or

d=$(TZ=UTC0 find test.txt -prune -printf '%TY%Tm%Td%TH%TM.%.2TS\n'

or

d=$(TZ=UTC0 stat -f %Sm -t %Y%m%d%H%M.%S text.txt)

Depending on whether you’ve got access to GNU date, GNU find or BSD stat (the idea being that unfortunately, there is (reasonably) no POSIX and reliable way to get the modification time of a file)

And then:

TZ=XXX-1 touch -t "$d" sooner
TZ=XXX+1 touch -t "$d" later
find . -newer sooner ! -newer later

The TZ=XXX<offset> format is standard and means defining the “XXX” timezone as being this <offset> to UTC, so the “UTC” or “XXX” in the TZ variables above are arbitrary and irrelevant.

Note that none of find -mmin, stat, find -printf, date +%s, date -r (let alone --reference) are portable or POSIX.

perl is generally more widely available than any of those, and you can do the whole thing with perl (using File::Find).

ksh93 or zsh (more easily) also have the ability to perform the whole task internally.

I said reasonably above, because it is possible to get the modification time of a file (as epoch time), provided its name is not too long and doesn’t contain newline characters, POSIXly, but it’s a bit convoluted:

{
  echo ibase=8
  printf '%s\n' test.txt |
    pax -x ustar -wd |
    dd 2> /dev/null bs=4 skip=34 count=3 |
    tr -d '\0'
  echo
} | bc

Converting it to a YYYYmmddHHMM.SS format in the UTC timezone POSIXly is also possible but also quite an effort (see http://stchaz.free.fr/wide_strftime.sh as an example)

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply