Reputation: 13
I have 1 directory with a lot of pdf files. This files are generated by another script that renames files with a progressive number for new version: (example)
newyork_v1.pdf
newyork_v2.pdf
newyork_v3.pdf
miami_v1.pdf
miami_v2.pdf
rome_v1.pdf
The version number is relative to the file, some files are a version 1, someone at version 2 etc like in example. Some files stay in version 1 for all own life, some files may grow to 10th version.
After copying this directory in a temp directory I'd like to delete old version for all files, in the example must remain:
newyork_v3.pdf
miami_v2.pdf
rome_v1.pdf
I try sort and delete by ls and sort command but I do not get the desired result, i try:
ls | sort -k2 -t_ -n -r | tail -n +2 | xargs rm
with this command stay only rome_v1.pdf
command or script are indifferent, can anyone help me?
Upvotes: 1
Views: 1469
Reputation: 2121
If you can use GNU ls, you can try below:
for p in $(ls -v *.pdf | cut -d_ -f1 | sort | uniq); do
ls -v $p* | head -n -1 | xargs -I{} rm {} 2>/dev/null
done
The -v flag of GNU ls sorts the files 'naturally' ie. in your case:
miami_v1.pdf
miami_v2.pdf
newyork_v1.pdf
newyork_v2.pdf
newyork_v3.pdf
newyork_v10.pdf #Added to show ls -v in action
rome_v1.pdf
We then loop through each uniq prefix and delete everything other than the last file which matches the prefix.
Result:
miami_v2.pdf
newyork_v10.pdf
rome_v1.pdf
Update:
Changed xargs to handle whitespace and special characters.
Upvotes: 2
Reputation: 20456
for file in $(ls *.pdf | awk -F'_' '{print $1}' | sort -u)
do
count=$(ls ${file}* | wc -l)
if [ ${count} -gt 1 ]; then
ls -rv ${file}* | tail -$(($count-1)) | xargs rm
fi
done
Upvotes: 4
Reputation: 15121
This Perl script can be used to filter out the old file names:
#!/usr/bin/perl
use warnings;
use strict;
my %files;
my @old_files;
while (<DATA>) {
chomp;
my ($name, $version, undef) = split /_v|\./, $_;
if (!$files{$name}->{version}) {
$files{$name}->{version} = $version;
$files{$name}->{name} = $_;
next;
}
if ($files{$name}->{version} < $version) {
push @old_files, $files{$name}->{name};
$files{$name}->{version} = $version;
$files{$name}->{name} = $_;
}
}
foreach my $file (@old_files) {
print "$file\n";
}
__DATA__
newyork_v1.pdf
newyork_v2.pdf
newyork_v3.pdf
miami_v1.pdf
miami_v2.pdf
rome_v1.pdf
Upvotes: 0