Get the last file name in a variable in bash?

4

2

In a directory, I have the following files:

myfile_v01.txt
myfile_v02.txt
myfile_v03.txt

How to make a bash script that detects the value of the last version and put the filename of this last version into a variable?

Vincent

Posted 2013-12-12T16:51:24.667

Reputation: 275

Answers

12

Not very refined but seems functional:

var=$(ls | sort -V | tail -n 1)

Then you have the last file stored in $var

Erathiel

Posted 2013-12-12T16:51:24.667

Reputation: 434

2

fyi: Why you shouldn't parse the output of ls(1) : http://mywiki.wooledge.org/ParsingLs

– MarZab – 2015-04-04T14:46:57.950

@MarZab Yes, you're right. I've seen that article already and it does have some valid points. – Erathiel – 2015-04-07T10:56:20.147

4

There are two obvious approaches, you can either parse the file name or look for the latest file:

  1. Parse the file name, this assumes all files are named as in your example:

    $ latest=myfile_v$(
        for f in myfile_v*; do 
          ver=${f##myfile_v}; ver=${ver%.txt}; echo $ver; 
        done | sort -n | tail -n 1).txt
    
  2. Get the newest file (assuming relatively sane file names that don't contain newlines)

    $ latest=$(ls -tr | tail -n 1)
    

terdon

Posted 2013-12-12T16:51:24.667

Reputation: 45 216

what does -tr option do ? – Ashildr – 2013-12-12T17:12:22.957

@Ash it sorts by time (-t) in reverse order (-r) so the last file is the newest – terdon – 2013-12-12T17:13:07.337

4

Here is a solution which uses globbing (so does not rely on parsing ls), like terdon's first solution, but doesn't need to iterate over all files:

myfiles=(myfile_v*)
lastfile="${myfiles[${#myfiles[@]}-1]}"
unset myfiles

First, all matching files are read into an array. Then, the last element of the array gets assigned to $lastfile. Finally, the array isn't needed anymore, so it can be deleted.

Unfortunately, bash (at least to my knowledge) doesn't support sorting the result from globbing#, so this example works fine with you given naming scheme (exactly two digits, also for versions < 10), but will fail for myfile_v1.txt, myfile_v2.txt, ..., myfile_v10.txt.


# zsh (of course ;)) does, so zsh% myfiles=(myfile_v*(n)); lastfile="${myfiles[-1]}"; unset myfiles wouldn't suffer from this limitation.

mpy

Posted 2013-12-12T16:51:24.667

Reputation: 20 866