[linux] Get most recent file in a directory on Linux

Looking for a command that will return the single most recent file in a directory.

Not seeing a limit parameter to ls...

This question is related to linux shell command-line

The answer is


ls -Frt | grep "[^/]$" | tail -n 1

try this simple command

ls -ltq  <path>  | head -n 1

If you want file name - last modified, path = /ab/cd/*.log

If you want directory name - last modified, path = /ab/cd/*/


A note about reliability:

Since the newline character is as valid as any in a file name, any solution that relies on lines like the head/tail based ones are flawed.

With GNU ls, another option is to use the --quoting-style=shell-always option and a bash array:

eval "files=($(ls -t --quoting-style=shell-always))"
((${#files[@]} > 0)) && printf '%s\n' "${files[0]}"

(add the -A option to ls if you also want to consider hidden files).

If you want to limit to regular files (disregard directories, fifos, devices, symlinks, sockets...), you'd need to resort to GNU find.

With bash 4.4 or newer (for readarray -d) and GNU coreutils 8.25 or newer (for cut -z):

readarray -t -d '' files < <(
  LC_ALL=C find . -maxdepth 1 -type f ! -name '.*' -printf '%T@/%f\0' |
  sort -rzn | cut -zd/ -f2)

((${#files[@]} > 0)) && printf '%s\n' "${files[0]}"

Or recursively:

readarray -t -d '' files < <(
  LC_ALL=C find . -name . -o -name '.*' -prune -o -type f -printf '%T@%p\0' |
  sort -rzn | cut -zd/ -f2-)

Best here would be to use zsh and its glob qualifiers instead of bash to avoid all this hassle:

Newest regular file in the current directory:

printf '%s\n' *(.om[1])

Including hidden ones:

printf '%s\n' *(D.om[1])

Second newest:

printf '%s\n' *(.om[2])

Check file age after symlink resolution:

printf '%s\n' *(-.om[1])

Recursively:

printf '%s\n' **/*(.om[1])

Also, with the completion system (compinit and co) enabled, Ctrl+Xm becomes a completer that expands to the newest file.

So:

vi Ctrl+Xm

Would make you edit the newest file (you also get a chance to see which it before you press Return).

vi Alt+2Ctrl+Xm

For the second-newest file.

vi *.cCtrl+Xm

for the newest c file.

vi *(.)Ctrl+Xm

for the newest regular file (not directory, nor fifo/device...), and so on.


using R recursive option .. you may consider this as enhancement for good answers here

ls -arRtlh | tail -50

Shorted variant based on dmckee's answer:

ls -t | head -1

ls -t -1 | sed '1q'

Will show the last modified item in the folder. Pair with grep to find latest entries with keywords

ls -t -1 | grep foo | sed '1q'

With only Bash builtins, closely following BashFAQ/003:

shopt -s nullglob

for f in * .*; do
    [[ -d $f ]] && continue
    [[ $f -nt $latest ]] && latest=$f
done

printf '%s\n' "$latest"

I needed to do it too, and I found these commands. these work for me:

If you want last file by its date of creation in folder(access time) :

ls -Aru | tail -n 1  

And if you want last file that has changes in its content (modify time) :

ls -Art | tail -n 1  

Presuming you don't care about hidden files that start with a .

ls -rt | tail -n 1

Otherwise

ls -Art | tail -n 1

Recursively:

find $1 -type f -exec stat --format '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head

I use:

ls -ABrt1 --group-directories-first | tail -n1

It gives me just the file name, excluding folders.


ls -lAtr | tail -1

The other solutions do not include files that start with '.'.

This command will also include '.' and '..', which may or may not be what you want:

ls -latr | tail -1


This is a recursive version (i.e. it finds the most recently updated file in a certain directory or any of its subdirectory)

find $DIR -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 2- | tail -n 1

Edit: use -f 2- instead of -f 2 as suggested by Kevin


If you want to get the most recent changed file also including any subdirectories you can do it with this little oneliner:

find . -type f -exec stat -c '%Y %n' {} \; | sort -nr | awk -v var="1" 'NR==1,NR==var {print $0}' | while read t f; do d=$(date -d @$t "+%b %d %T %Y"); echo "$d -- $f"; done

If you want to do the same not for changed files, but for accessed files you simple have to change the

%Y parameter from the stat command to %X. And your command for most recent accessed files looks like this:

find . -type f -exec stat -c '%X %n' {} \; | sort -nr | awk -v var="1" 'NR==1,NR==var {print $0}' | while read t f; do d=$(date -d @$t "+%b %d %T %Y"); echo "$d -- $f"; done

For both commands you also can change the var="1" parameter if you want to list more than just one file.


Finding the most current file in every directory according to a pattern, e.g. the sub directories of the working directory that have name ending with "tmp" (case insensitive):

find . -iname \*tmp -type d -exec sh -c "ls -lArt {} | tail -n 1" \;

ls -t | head -n1

This command actually gives the latest modified file in the current working directory.


All those ls/tail solutions work perfectly fine for files in a directory - ignoring subdirectories.

In order to include all files in your search (recursively), find can be used. gioele suggested sorting the formatted find output. But be careful with whitespaces (his suggestion doesn't work with whitespaces).

This should work with all file names:

find $DIR -type f -printf "%T@ %p\n" | sort -n | sed -r 's/^[0-9.]+\s+//' | tail -n 1 | xargs -I{} ls -l "{}"

This sorts by mtime, see man find:

%Ak    File's  last  access  time in the format specified by k, which is either `@' or a directive for the C `strftime' function.  The possible values for k are listed below; some of them might not be available on all systems, due to differences in `strftime' between systems.
       @      seconds since Jan. 1, 1970, 00:00 GMT, with fractional part.
%Ck    File's last status change time in the format specified by k, which is the same as for %A.
%Tk    File's last modification time in the format specified by k, which is the same as for %A.

So just replace %T with %C to sort by ctime.


I personally prefer to use as few not built-in bash commands as I can (to reduce the number of expensive fork and exec syscalls). To sort by date the ls needed to be called. But using of head is not really necessary. I use the following one-liner (works only on systems supporting name pipes):

read newest < <(ls -t *.log)

or to get the name of the oldest file

read oldest < <(ls -rt *.log)

(Mind the space between the two '<' marks!)

If the hidden files are also needed -A arg could be added.

I hope this could help.


I like echo *(om[1]) (zsh syntax) as that just gives the file name and doesn't invoke any other command.


The find / sort solution works great until the number of files gets really large (like an entire file system). Use awk instead to just keep track of the most recent file:

find $DIR -type f -printf "%T@ %p\n" | 
awk '
BEGIN { recent = 0; file = "" }
{
if ($1 > recent)
   {
   recent = $1;
   file = $0;
   }
}
END { print file; }' |
sed 's/^[0-9]*\.[0-9]* //'

Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to shell

Comparing a variable with a string python not working when redirecting from bash script Get first line of a shell command's output How to run shell script file using nodejs? Run bash command on jenkins pipeline Way to create multiline comments in Bash? How to do multiline shell script in Ansible How to check if a file exists in a shell script How to check if an environment variable exists and get its value? Curl to return http status code along with the response docker entrypoint running bash script gets "permission denied"

Examples related to command-line

Git is not working after macOS Update (xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools) Flutter command not found Angular - ng: command not found how to run python files in windows command prompt? How to run .NET Core console app from the command line Copy Paste in Bash on Ubuntu on Windows How to find which version of TensorFlow is installed in my system? How to install JQ on Mac by command-line? Python not working in the command line of git bash Run function in script from command line (Node JS)