Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'm looking for a shell one-liner to find the oldest file in a directory tree.

share|improve this question
add comment

4 Answers

up vote 13 down vote accepted

This works (updated to incorporate Daniel Andersson's suggestion):

find -type f -printf '%T+ %p\n' | sort | head -n 1
share|improve this answer
3  
Less typing: find -type f -printf '%T+ %p\n' | sort | head -1 –  Daniel Andersson Feb 15 '13 at 19:37
add comment
find ! -type d -printf "%T@ %p\n" | sort -n | head -n1
share|improve this answer
    
This won't work properly if there are files older than 9 Sep 2001 (1000000000 seconds since Unix epoch). To enable numeric sorting, use sort -n. –  Dennis Feb 16 '13 at 3:11
    
This helps find me the file, but it's hard to see how old it is without running a second command :) –  Marius Gedminas Feb 16 '13 at 9:38
add comment

The following commands commands are guaranteed to work with any kind of strange file names:

find -type f -printf "%T+ %p\0" | sort -z | grep -zom 1 ".*" | cat

find -type f -printf "%T@ %T+ %p\0" | \
    sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //'

stat -c "%y %n" "$(find -type f -printf "%T@ %p\0" | \
    sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //')"

Using a null byte (\0) instead of a linefeed character (\n) makes sure the output of find will still be understandable in case one of the file names contains a linefeed character.

The -z switch makes both sort and grep interpret only null bytes as end-of-line characters. Since there's no such switch for head, we use grep -m 1 instead (only one occurrence).

The commands are ordered by execution time (measured on my machine).

  • The first command will be the slowest since it has to convert every file's mtime into a human readable format first and then sort those strings. Piping to cat avoids coloring the output.

  • The second command is slightly faster. While it still performs the date conversion, numerically sorting (sort -n) the seconds elapsed since Unix epoch is a little quicker. sed deletes the seconds since Unix epoch.

  • The last command does no conversion at all and should be significantly faster than the first two. The find command itself will not display the mtime of the oldest file, so stat is needed.

Related man pages: findgrepsedsortstat

share|improve this answer
add comment

This one's a little more portable and because it doesn't rely on the GNU find extension -printf, so it works on BSD / OS X as well:

find . -type f -print0 | xargs -0 ls -ltr | head -n 1

The only downside here is that it's somewhat limited to the size of ARG_MAX (which should be irrelevant for most newer kernels). So, if there are more than getconf ARG_MAX characters returned (262,144 on my system), it doesn't give you the correct result. It's also not POSIX-compliant because -print0 and xargs -0 isn't.

Some more solutions to this problem are outlined here: How can I find the latest (newest, earliest, oldest) file in a directory? – Greg's Wiki

share|improve this answer
    
This works too, but it also emits an xargs: ls: terminated by signal 13 error as a side effect. I'm guessing that's SIGPIPE. I've no idea why I don't get a similar error when I pipe sort's output to head in my solution. –  Marius Gedminas Feb 15 '13 at 16:29
    
Your version is also easier to type from memory. :-) –  Marius Gedminas Feb 15 '13 at 16:29
    
Yes, that's a broken pipe. I don't get this with both GNU and BSD versions of all those commands, but it's the head command that quits once it has read a line and thus "breaks" the pipe, I think. You don't get the error because sort doesn't seem to complain about it, but ls does in the other case. –  slhck Feb 15 '13 at 16:32
3  
This breaks if there are so many filenames that xargs needs to invoke ls more than once. In that case, the sorted outputs of those multiple invocations end up concatenated when they should be merged. –  Nicole Hamilton Feb 15 '13 at 17:00
1  
I think this is worse than posting a script that assumes filenames never contain spaces. A lot of the time, those will work because the filenames don't have spaces. And when they fail, you get an error. But this is unlikely to work in real cases and failure will go undiscovered. On any directory tree big enough that you can't just ls it and eyeball the oldest file, your solution probably will overrun the command line length limit, causing ls to be invoked multiple times. You'll get the wrong answer but you'll never know. –  Nicole Hamilton Feb 15 '13 at 17:15
show 7 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.