7

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).

4 Answers 4

10

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.

2
  • This is a nice solution. Is there a way to return the actual number rather than the full file name? echo $latest would return 17 rather than filename_17.dat? Commented Jun 3, 2020 at 22:27
  • 1
    @agf1997 Use string manipulation to extract the number. For example number=${latest%.*}; number=${number#"${number%[!0-9]*}"?}; Commented Jun 4, 2020 at 8:03
9

ls(1) sorts files by name, so ls | tail -1 should do.

1
  • 3
    Or use -r for sorting in reverse order: ls -1r | head -1 Commented Mar 5, 2013 at 4:25
3

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.

2
  • +1 for mentioning 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 Commented Jun 24, 2022 at 18:52
  • 1
    @G-ManSays'ReinstateMonica' , thank you. I updated this answer, so it uses head and there is less computation on seeking after sort (1); added sorting for alphabetical solution (2); Commented Jun 26, 2022 at 12:50
0

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

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.