I have a list of dated files as below...
filename_20120101.dat
filename_20120102.dat
filename_20120103.dat
I need a script which selects the most recent file based on the date in the filename (not the file's date stamp).
Obligatory zsh answer:
echo "The highest-numbered file is" filename_*.dat([-1])
This is a glob with the glob qualifier [NUM] to retain only the NUMth match (a negative value counts from the last match). If you have numbers of varying width, add the n qualifier to
% ls
filename_1.dat filename_12.dat filename_17.dat filename_2.dat filename_8.dat
% echo filename_*.dat([-1])
filename_8.dat
% echo filename_*.dat(n[-1])
filename_17.dat
Globbing only happens in a context that looks for a list of words, so if you want to assign the filename to a variable, you need to make it an array which will contain one element:
latest=( filename_*.dat([-1]) )
echo "The highest-numbered file is $latest"
In any shell, you can set the positional arguments to the full list of matches and keep the last one.
set_latest () {
eval "latest=\${$#}"
}
set_latest filename_*.dat
echo "The highest-numbered file is $latest"
Keep in mind that this returns the last in alphabetical order, not in numerical order, e.g. filename_10.dat is after filename_09.dat but before filename_9.dat.
echo $latest would return 17 rather than filename_17.dat?
number=${latest%.*}; number=${number#"${number%[!0-9]*}"?};
ls(1) sorts files by name, so ls | tail -1 should do.
-r for sorting in reverse order: ls -1r | head -1
1-liner:
# for numerical order
find . -maxdepth 1 -name '*.dat' -print | sort -rV | head -n1
# for alphabetical order
find . -maxdepth 1 -name '*.dat' -print | sort -r | head -n1
Note: You can use ls instead of find.
sort -V. But (1) In situations like this, it is infinitesimally more efficient to sort so that the desired answer comes first, and then use head. (2) Your “alphabetical” answer will not work in general. find does not sort its output. If you are testing this in WSL or Cygwin, you are seeing the influence of the underlying Windows. (3) ls | tail -n1 was already given as an answer
head and there is less computation on seeking after sort (1); added sorting for alphabetical solution (2);
If the filenames are completely numerical, this needs to be piped through sort first, as ls will sort the files alphabetically, and 10 will occur before 9
$ touch {1..10)
$ ls | tail -1
> 9
$ ls | sort -n | tail -1
> 10