1

I was trying to figure out a way to retrieve the second lastest modified file name

With ls -tr I can get the list with the latest modified in the bottom. With tail -2 I can get the latest and the second latest

But I'm looking to pick just the second latest.

This is my trick to accomplish this:

ls -tr | tail -2 | tac | tail -1

But not sure if there is some more elegant way to execute this.

SirLouen
  • 137
  • 10
  • 1
    Not that you should be [parsing `ls`](http://mywiki.wooledge.org/ParsingLs), but can’t you simply pipe it to `head`? I.e. `ls -tr | tail -2 | head -1`. – Biffen Aug 25 '23 at 10:32
  • Did you try to pipe the result of `tail -2` through `head -1`...? – CiaPan Aug 25 '23 at 10:32
  • 1
    for manual interaction you can use: `ls -t | awk 'NR==2'` – Fravadona Aug 25 '23 at 10:34
  • This should help: https://en.wikipedia.org/wiki/Schwartzian_transform – Cyrus Aug 25 '23 at 10:45
  • Really nice solution with `awk` I completely forgot about that – SirLouen Aug 25 '23 at 10:46
  • Does this answer your question? [How to get the second latest file in a folder in Linux](https://stackoverflow.com/questions/16618370/how-to-get-the-second-latest-file-in-a-folder-in-linux) – pjh Aug 26 '23 at 01:03
  • @pjh I saw that but I did not like the solutions. My solution was purely noob, The solutions in that question were average level. And then here comes Ed Morton and Fravadona and showoff the super-pro way to do this. – SirLouen Aug 26 '23 at 14:18

2 Answers2

3

Assuming your file names don't contain newlines:

stat -c '%Y %n' * | sort -rn | awk 'NR==2{sub(/[^ ]+ /,""); print; exit}'

See Why you shouldn't parse the output of ls(1).

If your file names can contain newlines then with GNU tools:

stat --printf '%Y %n\0' * | sort -zrn | awk -v RS='\0' 'NR==2{sub(/[^ ]+ /,""); print; exit}'
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • I have to admit that I preferred the `ls -t | awk 'NR==2'` solution for its conciseness, but this looks better for correctness. This said, Idk why most people write in comments in SO, not answers anymore. Is there a fear of downvotes? – SirLouen Aug 26 '23 at 14:05
  • Sometimes it's people who aren't sure if their suggestion would help or think it'd only be partially useful rather than a complete answer. Other than that, idk. I do find myself asking people to post their answers as answers instead of comments once in a while. – Ed Morton Aug 27 '23 at 18:42
  • Conciseness is definitely nice but that's what you consider AFTER taking care of robustness, efficiency, portability, etc. – Ed Morton Aug 27 '23 at 18:44
0

If you've got Bash 4.0 (released in February 2009) or later and GNU Coreutils 9.0 (released in September 2021) or later, you can reliably put the name of the second newest file in the current directory into the variable latest2 with the code

readarray -d '' -s 1 -n 1 newest2 < <(ls -t --zero)

You could then, for instance, remove the file with

rm -- "$newest2"
  • The code works correctly for all filenames, including those containing newlines.
  • To demonstrate the technique clearly, the code above has no error checking. Code used for important work should check for errors like a failed ls or a directory that contains fewer than 2 files. That applies to other techniques for getting the second newest file too.
  • See the mapfile and Process Substitution sections of the Bash Reference Manual for explanations of readarray ... and <(...). (mapfile is an alternative name for readarray.)
  • The newest2 variable is really a Bash array with only one element. However, Bash allows the first element of an array to be accessed without using a subscript so $latest2 can be used instead of ${latest2[0]}.
pjh
  • 6,388
  • 2
  • 16
  • 17