Вопрос

Really not sure if I'm going about this the right way or not. I'm trying to rename files using the 7th lines in them (which is header information containing the title). The files are being put it via command line args; so ./perl.pl file1 file2 etc. What I've tried doing is taking the first argv and assigning it to an array @file1 and taking the 7th element and using that to rename, but to be honest I'm totally lost. Could anyone please show me how I could do this, either this way or another. My code that I was trying is:

 #!/usr/bin/perl

use strict;
use warnings;

my @file1 = $ARGV[0];
my @file2 = $ARGV[1];
my @file3 = $ARGV[2];
my @file4 = $ARGV[3];
my @file5 = $ARGV[4];

rename $ARGV[0], $file1[7];
rename $ARGV[1], $file2[7];
rename $ARGV[2], $file3[7];
rename $ARGV[3], $file4[7];
rename $ARGV[4], $file5[7];

Is there also perhaps a more flexible way of taking in the args so that I don't there can be more than 5 files input. Thanks guys

Это было полезно?

Решение

You can loop over @ARGV which are command line parameters, and rename each file by returning value of get_line().

get_line() opens $file for reading and when on 7-th line (if ($. == $n)), it removes newline (chomp $line) and returns content of 7-th line.

use strict;
use warnings;

sub get_line {
  my ($file, $n) = @_;

  open my $fh, "<", $file or die $!;
  while (my $line = <$fh>) {
    if ($. == $n) { chomp $line; return $line; }
  }
  return;
}

for my $file (@ARGV) {
  rename ($file, get_line($file, 7)) or warn $!;

}

Другие советы

Perl has some command line features to handle this smoothly:

perl -nlwe'if ($. == 7) { rename $ARGV, $_ or die $!; close ARGV; }' files*

This is the command line version of the longer code:

while (<>) {
    chomp;
    if ($. == 7) {
        rename $ARGV, $_ or die $!;
        close ARGV;
    }
}

This will loop over the contents of the files in the argument list @ARGV. When it comes to line 7, it will rename the file, then move on to the next file. Closing the file handle will both force a skip to next file, and reset the line counter $..

As a note on your algorithm, perhaps it would be wise to check so that files are not overwritten, such as

 if (! -e $_) { rename ... } else { warn "$_ already exists!" }

As mpapec says, it might be a good idea to take precaution against files with less than 7 lines that can potentially mess things up. The best way to do that in this case would be to check for a premature end of file eof

if ($. == 7) { # the regular check
    ...
} elsif (eof) {
    warn "File '$_' too short";
    close ARGV;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top