Skip to main content
this version doesn't use `map` (first version did but didn't do anything foreach couldn't and just made the script more complex for no good reason)
Source Link
cas
  • 84k
  • 8
  • 136
  • 205

Using perl:

$ perl -MFile::Basename -e '
  my @files = glob q(*.rar);

  my %bases;
  foreach (@files) {
    my ($b, $p) = split /\.part/, basename $_, q(.rar);
    $bases{$b} = $p if (!defined $bases{$b} or $p > $bases{$b});
  };

  foreach my $k (sort keys %bases) {
    print "$k.part$bases{$k}.rar\n"
  }'
1yBWVnZCx8CoPrGIG.part23.rar
DaHs0QJnJbt.part4.rar
RSmWMPb0vWr8LIEFtR7o.part5.rar
T7yvBIqHK82qDCNTtz9iuvp2NhQ.part11.rar
W1Pn8SHf7pbMSf1u99C4f.part2.rar
XYcUpv7b1ZpcczFT5y7Uc9mQTvAf88kl.part2.rar
n5oTzoLvG.part6.rar
okgbuh8VUxSguDNra9uMTtDlXhiLWQmY.part2.rar
tBJDjsyJtFpY0d3aQ.part6.rar

This firstFirst this gets all the filenames matching the glob *.rar into an array called @files. Then it uses map to convertconverts the array into a hash (aka associative array) called %bases where each key is the base filename and the value is the highest part number seen for that basename.

Then it prints out each basename with the part number in the same format as the original filenames: base.partN.rar

This uses the File::Basename module, which is included with perl as part of its standard library.

There are shorter, more obfuscated ways to do this in perl, but this IMO is a nice balance between brevity and readability. It was written to pass the restrictions of use strict (or -Mstrict on the command-line), so it could be re-used as part of a larger script. That's why there are all the my declarations that are usually skipped for one-liners.

Using perl:

$ perl -MFile::Basename -e '
  my @files = glob q(*.rar);

  my %bases;
  foreach (@files) {
    my ($b, $p) = split /\.part/, basename $_, q(.rar);
    $bases{$b} = $p if (!defined $bases{$b} or $p > $bases{$b});
  };

  foreach my $k (sort keys %bases) {
    print "$k.part$bases{$k}.rar\n"
  }'
1yBWVnZCx8CoPrGIG.part23.rar
DaHs0QJnJbt.part4.rar
RSmWMPb0vWr8LIEFtR7o.part5.rar
T7yvBIqHK82qDCNTtz9iuvp2NhQ.part11.rar
W1Pn8SHf7pbMSf1u99C4f.part2.rar
XYcUpv7b1ZpcczFT5y7Uc9mQTvAf88kl.part2.rar
n5oTzoLvG.part6.rar
okgbuh8VUxSguDNra9uMTtDlXhiLWQmY.part2.rar
tBJDjsyJtFpY0d3aQ.part6.rar

This first gets all the filenames matching the glob *.rar into an array called @files. Then it uses map to convert the array into a hash (aka associative array) called %bases where each key is the base filename and the value is the highest part number seen for that basename.

Then it prints out each basename with the part number in the same format as the original filenames: base.partN.rar

This uses the File::Basename module, which is included with perl as part of its standard library.

There are shorter, more obfuscated ways to do this in perl, but this IMO is a nice balance between brevity and readability. It was written to pass the restrictions of use strict (or -Mstrict on the command-line), so it could be re-used as part of a larger script. That's why there are all the my declarations that are usually skipped for one-liners.

Using perl:

$ perl -MFile::Basename -e '
  my @files = glob q(*.rar);

  my %bases;
  foreach (@files) {
    my ($b, $p) = split /\.part/, basename $_, q(.rar);
    $bases{$b} = $p if (!defined $bases{$b} or $p > $bases{$b});
  };

  foreach my $k (sort keys %bases) {
    print "$k.part$bases{$k}.rar\n"
  }'
1yBWVnZCx8CoPrGIG.part23.rar
DaHs0QJnJbt.part4.rar
RSmWMPb0vWr8LIEFtR7o.part5.rar
T7yvBIqHK82qDCNTtz9iuvp2NhQ.part11.rar
W1Pn8SHf7pbMSf1u99C4f.part2.rar
XYcUpv7b1ZpcczFT5y7Uc9mQTvAf88kl.part2.rar
n5oTzoLvG.part6.rar
okgbuh8VUxSguDNra9uMTtDlXhiLWQmY.part2.rar
tBJDjsyJtFpY0d3aQ.part6.rar

First this gets all the filenames matching the glob *.rar into an array called @files. Then it converts the array into a hash (aka associative array) called %bases where each key is the base filename and the value is the highest part number seen for that basename.

Then it prints out each basename with the part number in the same format as the original filenames: base.partN.rar

This uses the File::Basename module, which is included with perl as part of its standard library.

There are shorter, more obfuscated ways to do this in perl, but this IMO is a nice balance between brevity and readability. It was written to pass the restrictions of use strict (or -Mstrict on the command-line), so it could be re-used as part of a larger script. That's why there are all the my declarations that are usually skipped for one-liners.

Source Link
cas
  • 84k
  • 8
  • 136
  • 205

Using perl:

$ perl -MFile::Basename -e '
  my @files = glob q(*.rar);

  my %bases;
  foreach (@files) {
    my ($b, $p) = split /\.part/, basename $_, q(.rar);
    $bases{$b} = $p if (!defined $bases{$b} or $p > $bases{$b});
  };

  foreach my $k (sort keys %bases) {
    print "$k.part$bases{$k}.rar\n"
  }'
1yBWVnZCx8CoPrGIG.part23.rar
DaHs0QJnJbt.part4.rar
RSmWMPb0vWr8LIEFtR7o.part5.rar
T7yvBIqHK82qDCNTtz9iuvp2NhQ.part11.rar
W1Pn8SHf7pbMSf1u99C4f.part2.rar
XYcUpv7b1ZpcczFT5y7Uc9mQTvAf88kl.part2.rar
n5oTzoLvG.part6.rar
okgbuh8VUxSguDNra9uMTtDlXhiLWQmY.part2.rar
tBJDjsyJtFpY0d3aQ.part6.rar

This first gets all the filenames matching the glob *.rar into an array called @files. Then it uses map to convert the array into a hash (aka associative array) called %bases where each key is the base filename and the value is the highest part number seen for that basename.

Then it prints out each basename with the part number in the same format as the original filenames: base.partN.rar

This uses the File::Basename module, which is included with perl as part of its standard library.

There are shorter, more obfuscated ways to do this in perl, but this IMO is a nice balance between brevity and readability. It was written to pass the restrictions of use strict (or -Mstrict on the command-line), so it could be re-used as part of a larger script. That's why there are all the my declarations that are usually skipped for one-liners.