Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to recursively find the latest modified file in a directory?

People also ask

How do I find the latest modified file in Linux?

Finding Files Modified on a Specific Date in Linux: You can use the ls command to list files including their modification date by adding the -lt flag as shown in the example below. The flag -l is used to format the output as a log. The flag -t is used to list last modified files, newer first.

How can I tell when a file was last modified?

File Explorer has a convenient way to search recently modified files built right into the “Search” tab on the Ribbon. Switch to the “Search” tab, click the “Date Modified” button, and then select a range. If you don't see the “Search” tab, click once in the search box and it should appear.

How will check the last update of a directory or a file?

date command with -r option followed by the name of file will display the last modified date and time of the file. which is the last modified date and time of the given file. date command can also be used to determine the last modified date of a directory.


find . -type f -printf '%T@ %p\n' \
| sort -n | tail -1 | cut -f2- -d" "

For a huge tree, it might be hard for sort to keep everything in memory.

%T@ gives you the modification time like a unix timestamp, sort -n sorts numerically, tail -1 takes the last line (highest timestamp), cut -f2 -d" " cuts away the first field (the timestamp) from the output.

Edit: Just as -printf is probably GNU-only, ajreals usage of stat -c is too. Although it is possible to do the same on BSD, the options for formatting is different (-f "%m %N" it would seem)

And I missed the part of plural; if you want more then the latest file, just bump up the tail argument.


Following up on @plundra's answer, here's the BSD and OS X version:

find . -type f -print0 \
| xargs -0 stat -f "%m %N" \
| sort -rn | head -1 | cut -f2- -d" "

Instead of sorting the results and keeping only the last modified ones, you could use awk to print only the one with greatest modification time (in unix time):

find . -type f -printf "%T@\0%p\0" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\0'

This should be a faster way to solve your problem if the number of files is big enough.

I have used the NUL character (i.e. '\0') because, theoretically, a filename may contain any character (including space and newline) but that.

If you don't have such pathological filenames in your system you can use the newline character as well:

find . -type f -printf "%T@\n%p\n" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\n'

In addition, this works in mawk too.


I had the trouble to find the last modified file under Solaris 10. There find does not have the printf option and stat is not available. I discovered the following solution which works well for me:

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1

To show the filename as well use

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1

Explanation

  • find . -type f finds and lists all files
  • sed 's/.*/"&"/' wraps the pathname in quotes to handle whitespaces
  • xargs ls -E sends the quoted path to ls, the -E option makes sure that a full timestamp (format year-month-day hour-minute-seconds-nanoseconds) is returned
  • awk '{ print $6," ",$7 }' extracts only date and time
  • awk '{ print $6," ",$7," ",$9 }' extracts date, time and filename
  • sort returns the files sorted by date
  • tail -1 returns only the last modified file

This seems to work fine, even with subdirectories:

find . -type f | xargs ls -ltr | tail -n 1

In case of too many files, refine the find.