Looking for a command that will return the single most recent file in a directory.
Not seeing a limit parameter to ls
...
ls -t | head -n1
This command actually gives the latest modified file in the current working directory.
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.
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
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
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"