121

I want to check in linux bash whether a file was created more than x time ago.

let's say the file is called text.txt and the time is 2 hours.

 if [ what? ]
 then
     echo "old enough"
 fi
Guss
  • 30,470
  • 17
  • 104
  • 128
flybywire
  • 261,858
  • 191
  • 397
  • 503

8 Answers8

166

Only for modification time

if test `find "text.txt" -mmin +120`
then
    echo old enough
fi

You can use -cmin for change or -amin for access time. As others pointed I don’t think you can track creation time.

kmkaplan
  • 18,655
  • 4
  • 51
  • 65
51

I always liked using date -r /the/file +%s to find its age.

You can also do touch --date '2015-10-10 9:55' /tmp/file to get extremely fine-grained time on an arbitrary date/time.

Theodore R. Smith
  • 21,848
  • 12
  • 65
  • 91
nemik
  • 658
  • 6
  • 5
  • I was looking for same thing today. Best! – Umair A. Jan 04 '14 at 20:26
  • Thanks. I landed on this SO question because I googled "how to print age of file bash." So this is exactly what I was looking for! – Noah Sussman Sep 16 '15 at 18:52
  • 6
    Thanks! with the only caveat that the above is a timestamp (not age) but can be used to calc the age like so `let AGE=$(($(date +%s)-$(date -r /path/to/file +%s)))` [with the assumption that created and never modified, or "age relative to mod"] – nhed Nov 16 '16 at 17:58
  • ```function file-age { FILE_CREATED_TIME=`date -r "$1" +%s`; TIME_NOW=`date +%s`; echo "$[ ${TIME_NOW} - ${FILE_CREATED_TIME} ]"; } ``` – turiyag Apr 28 '18 at 18:50
  • 1
    @turiyag Obligatory note that `$[ ]` is, if not *deprecated*, at least *old and less portable*, and one should use `$(( ))` instead; and backquotes are more fragile than `$( )`; and also hyphens in function names may not be fully portable. The essence of it is good, though! – michaelb958--GoFundMonica Mar 18 '19 at 03:54
  • This answer has some good information but does **not** answer the question. – Dem Pilafian Jun 15 '19 at 02:08
  • ```file_age() { local created local now created=$(date -r "$1" +%s) now=$(date +%s) echo "$(( now - created ))" } ``` – bryce Mar 27 '22 at 03:51
32

Using the stat to figure out the last modification date of the file, date to figure out the current time and a liberal use of bashisms, one can do the test that you want based on the file's last modification time1.

if [ "$(( $(date +"%s") - $(stat -c "%Y" "$somefile") ))" -gt "7200" ]; then
   echo "'$somefile' is older then 2 hours"
fi

While the code is a bit less readable then the find approach, I think its a better approach then running find to look at a file you already "found". Also, date manipulation is fun ;-)


  1. As Phil correctly noted creation time is not recorded, but use %Z instead of %Y below to get "change time" which may be what you want.

[Update]

For mac users, use stat -f "%m" "$somefile" instead of the Linux specific syntax above

Guss
  • 30,470
  • 17
  • 104
  • 128
  • What shell are date and stat built in to? My bash (GNU, 3.2.48) doesn't have them. – Ian Clelland Sep 09 '09 at 19:35
  • oops, sorry. `stat` is not builtin - very bad of me, I'll fix. – Guss Sep 09 '09 at 19:45
  • @tommy.carstensen - I don't have a mac available. Can you please describe what doesn't work? Also, are you using bash? I know many Macists prefer zsh. – Guss Jan 24 '15 at 16:13
  • I've added a note for mac users. – Guss Jan 25 '15 at 13:29
  • 1
    @Guss right solution is to install coretutils with brew. :-) – Erik Johansson Feb 14 '15 at 23:29
  • 1
    @ErikJohansson I prefer not to require installation of additional software when using the existing one works fine - this isn't Windows, you know ;-) – Guss Feb 16 '15 at 09:24
  • 1
    For people who want to use this but modify it, it would be good to know exactly what it is doing: $(( $(date +"%s") -- seconds since 1970-01-01 00:00:00 UTC (Epoch) $(stat -c "%Y" $somefile) )) -- Time of last modification as seconds since Epoch -gt "7200" -- checks if the difference is greater than x number of seconds. – devo Mar 02 '16 at 18:38
  • @Guss Thanks for updating the answer. This is now the best answer. – tommy.carstensen Mar 02 '18 at 12:59
  • @Ian Clelland stat and date are standard gnu tools, common on most linux installs https://www.gnu.org/software/coreutils/manual/html_node/stat-invocation.html#stat-invocation https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html#date-invocation – Jasen Nov 05 '19 at 19:54
  • 1
    You should always quote variables that might contain spaces or special characters, e.g. `"$somefile"`. (It's the only parameter there that really needs quoting.) – mwfearnley Apr 04 '22 at 16:16
17

Creation time isn't stored.

What are stored are three timestamps (generally, they can be turned off on certain filesystems or by certain filesystem options):

  • Last access time
  • Last modification time
  • Last change time

a "Change" to the file is counted as permission changes, rename etc. While the modification is contents only.

Philip Reynolds
  • 9,364
  • 3
  • 30
  • 37
13

Although ctime isn't technically the time of creation, it quite often is.

Since ctime it isn't affected by changes to the contents of the file, it's usually only updated when the file is created. And yes - I can hear you all screaming - it's also updated if you change the access permissions or ownership... but generally that's something that's done once, usually at the same time you put the file there.

Personally I always use mtime for everything, and I imagine that is what you want. But anyway... here's a rehash of Guss's "unattractive" bash, in an easy to use function.

#!/bin/bash
function age() {
   local filename=$1
   local changed=`stat -c %Y "$filename"`
   local now=`date +%s`
   local elapsed

   let elapsed=now-changed
   echo $elapsed
}

file="/"
echo The age of $file is $(age "$file") seconds.
Maryam Jeddian
  • 261
  • 3
  • 4
  • This was useful, but it didn't work right away for OSX because stat is implemented differently on it. The only cross-system compatible way I found was to use perl. The script should work on Macs if you replace the corresponding line with this: `local changed=$(perl -MFile::stat -e "print stat(\"${filename}\")->mtime")` http://superuser.com/questions/427551/is-there-a-cross-nix-compatible-way-to-get-file-modified-timestamp – Bijou Trouvaille May 29 '13 at 23:45
  • 2
    "Creation time" is a concept hard to grasp. What does it mean for a copied file? What for a moved file? What if it was moved across a device border (so it got created anew, in a sense)? What does it mean for a packaged and later unpackaged file? Several answers are possible here and no consensus exists. Mentioning the ctime is nice, though, but I wouldn't put it semantically near the vague concept of a "creation time". Especially since a simple `chmod`, applied on the file, will nullify that idea. But I can live with *you* doing that ;-) – Alfe Oct 06 '14 at 10:08
  • @Alfe: You're missing the `+%s` from the second half – Grizly Oct 08 '14 at 00:19
  • That age can be way shorter: `age() { echo $(( $(date +%s) - $(date -r "$1" +%s) )); }` (Thanks to @Grizly for the correction!) – Alfe Oct 08 '14 at 07:39
  • Actually it's better to use access time which is a creation time on all file systems mounted with `noatime` option (which is good for performance so you should use it). So just use `%X` instead of `%Y`. – Nux May 26 '15 at 07:37
9

The find one is good but I think you can use anotherway, especially if you need to now how many seconds is the file old

date -d "now - $( stat -c "%Y" $filename ) seconds" +%s

using GNU date

Vide
  • 91
  • 1
  • 1
5

Consider the outcome of the tool 'stat':

  File: `infolog.txt'
  Size: 694         Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 11635578    Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/     fdr)   Gid: ( 1000/     fdr)
Access: 2009-01-01 22:04:15.000000000 -0800
Modify: 2009-01-01 22:05:05.000000000 -0800
Change: 2009-01-01 22:05:05.000000000 -0800

You can see here the three dates for Access/modify/change. There is no created date. You can only really be sure when the file contents were modified (the "modify" field) or its inode changed (the "change" field).

Examples of when both fields get updated:

"Modify" will be updated if someone concatenated extra information to the end of the file.

"Change" will be updated if someone changed permissions via chmod.

fdr
  • 391
  • 1
  • 8
  • granted, stat can tell you relevant information. But it will be quite tedious to parse in order to get what we want. – PypeBros Dec 07 '17 at 09:31
0

I use

file_age() {
    local filename=$1
    echo $(( $(date +%s) - $(date -r $filename +%s) ))
}

is_stale() {
    local filename=$1
    local max_minutes=20
    [ $(file_age $filename) -gt $(( $max_minutes*60 )) ]
}

if is_stale /my/file; then
    ...
fi
xpmatteo
  • 11,156
  • 3
  • 26
  • 25