0

I have a directory of files with similar names, but with incrementing digits as a suffix. I want to remove the lower suffixed files and only keep the files with the highest suffix. Below is an example file listing:

1k_02.txt
1k_03.txt
1l_02.txt
1l_03.txt
1l_04.txt
2a_05.txt
2a_06.txt
4c_03.txt
4c_04.txt

The above list needs to be reduced to the files below:

1k_03.txt
1l_04.txt
2a_06.txt
4c_04.txt

I don't even know where to start with this, but if possible I would like a single bash command.

5
  • explain your removing logic, how files with duplicate suffixes should be processed? Why 1k_03.txt should be kept but 4c_03.txt should be removed? Commented Nov 29, 2017 at 20:07
  • There’s different prefixes for each.
    – Jeff Schaller
    Commented Nov 29, 2017 at 20:08
  • @user - are you opposed to a zsh-based command that would accomplish the goal? I don’t know one, but suspect there may be. e.g. zsh -c ‘rm ....’
    – Jeff Schaller
    Commented Nov 29, 2017 at 20:09
  • @RomanPerekhrest - The suffix is a version number for the file; I want to keep the highest version of each file and remove the remainder, but not all files were incremented uniformly. Unfortunately the date stamps were all reset so all I have to go by are the file names.
    – user300457
    Commented Nov 29, 2017 at 20:42
  • @JeffSchaller - Anything goes, although I've never used zsh.
    – user300457
    Commented Nov 29, 2017 at 20:43

2 Answers 2

1

Complex pipeline:

Files list:

$ ls
1l_04.txt 2a_05.txt 4c_03.txt 1k_03.txt 1l_02.txt 4c_04.txt 2a_06.txt 1l_03.txt 1k_02.txt

printf "%s\n" * | sort -t'_' -k1,1 -k2nr | awk -F'_' 'a[$1]++' | xargs rm

Results:

$ printf "%s\n" *
1k_03.txt
1l_04.txt
2a_06.txt
4c_04.txt
0
1

With zsh:

$ ls
1k_02.txt  1l_02.txt  1l_04.txt  2a_06.txt  4c_04.txt
1k_03.txt  1l_03.txt  2a_05.txt  4c_03.txt
$ (typeset -A seen; for f (*_*(nOn)) let 'seen[${f%_*}]++' && rm -- $f)
$ ls
1k_03.txt  1l_04.txt  2a_06.txt  4c_04.txt

(see How to use associative arrays safely inside arithmetic expressions? for why we're using let instead of ((...)) here).

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .