-1

I have a directory of versioned files. The version of each file is indicated within it's filename, e.g. "_v1".

Example

List of files shown by ls:

123_FileA_v1.txt
123_FileA_v2.txt
132_FileB_v1.txt

I want to run a command to see only the latest versions:

123_FileA_v2.txt
132_FileB_v1.txt

My first attempt was to list files by mtime using

ls -ltr

But in my case this doesn't lead to sufficient results. I really want to collect versions from the filenames.

What would be the best way to do it?

jschnasse
  • 8,526
  • 6
  • 32
  • 72
  • 4
    By the way, question who do not show any effort on solving them on your own are frowned upon on this site. Not to mention you will get downvotes. – Matias Barrios Feb 27 '20 at 13:45
  • 2
    Vote for reopen. New user has ask an okay question. OP is not asking for code. (I see no urging need for own attempt). Question has been edited since close vote. – jschnasse Feb 28 '20 at 07:49
  • 1
    Thanks @jschnasse, good to see dissent from the mindless army of "what have you tried" bots. There are literally dozens of us! And welcome user12973426, this is an interesting puzzle. – Don Hatch Feb 28 '20 at 09:07
  • Thanks all, Sorry it’s my first time posting here I’ll take note of it and show more effort visibly in the future questions – user12973426 Mar 01 '20 at 01:18

2 Answers2

1

This will do it :

ls | awk -F '_' '!prefixes[$1]++'

Hope it helps!

Edit :

If you want to see specific info you can do :

ls | awk -F '_' '!prefixes[$1]++' | xargs ls -lh

This will work as long as there are not spaces in your filenames.

Edit :

As requested by @PaulHodges, here is the sample output :_

$ ls -lh
total 0
drwxr-xr-x    5 Matias-Barrios  Matias-Barrios   160B Feb 27 11:40 .
drwxr-xr-x  106 Matias-Barrios  Matias-Barrios   3.3K Feb 27 11:39 ..
-rw-r--r--    1 Matias-Barrios  Matias-Barrios     0B Feb 27 11:40 132_FileB_v1.txt
-rw-r--r--    1 Matias-Barrios  Matias-Barrios     0B Feb 27 11:40 123_FileA_v2.txt
-rw-r--r--    1 Matias-Barrios  Matias-Barrios     0B Feb 27 11:40 123_FileA_v1.txt
$ ls | awk -F '_' '!prefixes[$1]++' 
.
..
132_FileB_v1.txt
123_FileA_v2.txt
Community
  • 1
  • 1
Matias Barrios
  • 4,674
  • 3
  • 22
  • 49
0

You could do something like

( 
PATTERN="[0-9]{3}_[^_]*" 
for prefix in `find . | egrep -o "$PATTERN" | sort -u`; 
do 
   ls $prefix* | tail -1; 
done
)

It will print

123_FileA_v2.txt
132_FileB_v1.txt

What happens here?

  • The surrounding braces ( are used to support copy & paste of the provided code. read more
  • The variable PATTERN is used to access all files starting with the same prefix.
  • The for prefix in `find . | egrep -o "$PATTERN" | sort -u generates a list of file prefixes.
  • The ls $prefix* lists all files with the same prefix in alphanumerical order
  • The | tail -1 shows only the last entry of the former ls $prefix*

Edit

I decided to use find . instead of ls *. With that I hope to circumvent the issues with ls *. Please correct me, if I'm wrong!

jschnasse
  • 8,526
  • 6
  • 32
  • 72
  • 3
    Now do it without [parsing ls](https://mywiki.wooledge.org/ParsingLshttps://mywiki.wooledge.org/ParsingLs). – Paul Hodges Feb 27 '20 at 14:09
  • Thanks this works but when the file list gets huge it’s seems to get a bit slow possibly due to the ls within the loop – user12973426 Mar 01 '20 at 01:16