How can I tell if a file is older than 30 minutes from /bin/sh?

LinuxUnixSh

Linux Problem Overview


How do I write a script to determine if a file is older than 30 minutes in /bin/sh?

Unfortunately does not the stat command exist in the system. It is an old Unix system, http://en.wikipedia.org/wiki/Interactive_Unix

Perl is unfortunately not installed on the system and the customer does not want to install it, and nothing else either.

Linux Solutions


Solution 1 - Linux

Here's one way using find.

if test "`find file -mmin +30`"

The find command must be quoted in case the file in question contains spaces or special characters.

Solution 2 - Linux

The following gives you the file age in seconds:

echo $(( `date +%s` - `stat -L --format %Y $filename` ))

which means this should give a true/false value (1/0) for files older than 30 minutes:

echo $(( (`date +%s` - `stat -L --format %Y $filename`) > (30*60) ))

30*60 -- 60 seconds in a minute, don't precalculate, let the CPU do the work for you!

Solution 3 - Linux

If you're writing a sh script, the most useful way is to use test with the already mentioned stat trick:

if [ `stat --format=%Y $file` -le $(( `date +%s` - 1800 )) ]; then 
    do stuff with your 30-minutes-old $file
fi

Note that [ is a symbolic link (or otherwise equivalent) to test; see man test, but keep in mind that test and [ are also bash builtins and thus can have slightly different behavior. (Also note the [[ bash compound command).

Solution 4 - Linux

Ok, no stat and a crippled find. Here's your alternatives:

Compile the GNU coreutils to get a decent find (and a lot of other handy commands). You might already have it as gfind.

Maybe you can use date to get the file modification time if -r works?

(`date +%s` - `date -r $file +%s`) > (30*60)

Alternatively, use the -nt comparision to choose which file is newer, trouble is making a file with a mod time 30 minutes in the past. touch can usually do that, but all bets are off as to what's available.

touch -d '30 minutes ago' 30_minutes_ago
if [ your_file -ot 30_minutes_ago ]; then
    ...do stuff...
fi

And finally, see if Perl is available rather than struggling with who knows what versions of shell utilities.

use File::stat;
print "Yes" if (time - stat("yourfile")->mtime) > 60*30;

Solution 5 - Linux

For those like myself, who don't like back ticks, based on answer by @slebetman:

echo $(( $(date +%s) - $(stat -L --format %Y $filename) > (30*60) ))

Solution 6 - Linux

You can do this by comparing to a reference file that you've created with a timestamp of thirty minutes ago.

First create your comparison file by entering

touch -t YYYYMMDDhhmm.ss /tmp/thirty_minutes_ago

replacing the timestamp with the value thirty minutes ago. You could automate this step with a trivial one liner in Perl.

Then use find's newer operator to match files that are older by negating the search operator

find . \! -newer /tmp/thirty_minutes_ago -print

Solution 7 - Linux

Difference in seconds between current time and last modification time of myfile.txt:

echo $(($(date +%s)-$(stat -c "%Y" myfile.txt)))

you can also use %X or %Z with the command stat -c to get the difference between last access or last status change, check for 0 return!

%X time of last access, seconds since Epoch
%Y time of last data modification, seconds since Epoch
%Z time of last status change, seconds since Epoch

The test:

if [ $(($(date +%s)-$(stat -c "%Y" myfile.txt))) -lt 600 ] ; then echo younger than 600 sec ; else echo older than 600 sec ; fi

Solution 8 - Linux

What do you mean by older than 30 minutes: modified more than 30 minutes ago, or created more than 30 minutes ago? Hopefully it's the former, as the answers so far are correct for that interpretation. In the latter case, you have problems since unix file systems do not track the creation time of a file. (The ctime file attribute records when the inode contents last changed, ie, something like chmod or chown happened).

If you really need to know if file was created more than 30 minutes ago, you'll either have to scan the relevant part of the file system repeatedly with something like find or use something platform-dependent like linux's inotify.

Solution 9 - Linux

#!/usr/bin/ksh
## this script creates a new timer file every minute and renames all the previously created timer files and then executes whatever script you need which can now use the timer files to compare against with a find.  The script is designed to always be running on the server.  The first time the script is executed it will remove the timer files and it will take an hour to rebuild them (assuming you want 60 minutes of timer files)

set -x

# if the server is rebooted for any reason or this scripts stops we must rebuild the timer files from scratch
find /yourpath/timer -type f -exec rm {} \;

while [ 1 ]
do
COUNTER=60
COUNTER2=60
cd /yourpath/timer
while [ COUNTER -gt 1 ]
do
  COUNTER2=`expr $COUNTER - 1`
  echo COUNTER=$COUNTER
  echo COUNTER2=$COUNTER2
  if [  -f timer-minutes-$COUNTER2 ]
    then
       mv timer-minutes-$COUNTER2 timer-minutes-$COUNTER
       COUNTER=`expr $COUNTER - 1`
  else
     touch timer-minutes-$COUNTER2
  fi
done

touch timer-minutes-1
sleep 60

#this will check to see if the files have been fully updated after a server restart
COUNT=`find . ! -newer timer-minutes-30 -type f | wc -l | awk '{print $1}'`
if [ $COUNT -eq 1  ]
   then
     # execute whatever scripts at this point
fi

done

Solution 10 - Linux

You can use the find command.
For example, to search for files in current dir that are older than 30 min:

find . -type f -mmin +30 

You can read up about the find command HERE

Solution 11 - Linux

Here's my variation on find:

if [ `find cache/nodes.csv -mmin +10 | egrep '.*'` ]

Find always returns status code 0 unless it fails; however, egrep returns 1 is no match is found`. So this combination passes if that file is older than 10 minutes.

Try it:

touch /tmp/foo; sleep 61; 
find /tmp/foo -mmin +1  | egrep '.*'; echo $?
find /tmp/foo -mmin +10 | egrep '.*'; echo $?

Should print 0 and then 1 after the file's path.

My function using this:

##  Usage: if isFileOlderThanMinutes "$NODES_FILE_RAW" $NODES_INFO_EXPIRY; then ...
function isFileOlderThanMinutes {
  if [ "" == "$1" ] ; then serr "isFileOlderThanMinutes() usage: isFileOlderThanMinutes <file> <minutes>"; exit; fi
  if [ "" == "$2" ] ; then serr "isFileOlderThanMinutes() usage: isFileOlderThanMinutes <file> <minutes>"; exit; fi
  ##  Does not exist -> "older"
  if [ ! -f "$1" ] ; then return 0; fi
  ##  The file older than $2 is found...
  find "$1" -mmin +$2 | egrep '.*'  > /dev/null 2>&1;
  if [ $? == 0 ] ; then return 0; fi  ## So it is older.
  return 1;  ## Else it not older.
}

Solution 12 - Linux

if [[ "$(date --rfc-3339=ns -r /tmp/targetFile)" < "$(date --rfc-3339=ns --date '90 minutes ago')" ]] ; then echo "older"; fi

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmagolView Question on Stackoverflow
Solution 1 - LinuxSchwernView Answer on Stackoverflow
Solution 2 - LinuxslebetmanView Answer on Stackoverflow
Solution 3 - LinuxalvherreView Answer on Stackoverflow
Solution 4 - LinuxSchwernView Answer on Stackoverflow
Solution 5 - Linuxtommy.carstensenView Answer on Stackoverflow
Solution 6 - LinuxRob WellsView Answer on Stackoverflow
Solution 7 - LinuxBert-JanView Answer on Stackoverflow
Solution 8 - LinuxDale HagglundView Answer on Stackoverflow
Solution 9 - LinuxddertonView Answer on Stackoverflow
Solution 10 - Linuxmighty_mikeView Answer on Stackoverflow
Solution 11 - LinuxOndra ŽižkaView Answer on Stackoverflow
Solution 12 - Linuxuser8050735View Answer on Stackoverflow