Несколько проблем с этим кодом:
Использование идентификатора без слов старой школы для дескриптора каталога вместо переменной с автовыводом, как вы для дескриптора файла.
Использование одной и той же переменной для имени файла и дескриптора файла довольно странно.
Вы не проверяете, является ли файл каталогом или чем-то другим чем обычный файл, прежде чем пытаться его открыть.
$27
?
Вы никогда ничего не назначаете этой переменной $line
перед печатью it.
Если $directory
не является текущим рабочим каталогом вашей программы, вы столкнулись с проблемой, упомянутой в readdir
документации
Если вы планируете подавать возвращаемые значения из readdir, вам лучше добавить соответствующий каталог. В противном случае, поскольку мы не сделали chdir там, он бы проверял неверный файл.
(Заменить открытым для проверки файла)
Всегда use strict;
и use warnings;
.
Лично, если вы просто хотите напечатать 27-ю строку большого количества файлов, я бы обратился к awk
и find
(с помощью теста -exec
, чтобы избежать потенциальных ошибок, связанных с максимальной длиной командной строки):
find directory/ -maxdepth 1 -type -f -exec awk 'FNR == 27 { print FILENAME; print }' \{\} \+
Если вы используете систему Windows без стандарта unix инструменты, подобные установленным, или это часть более крупной программы, исправленный perl
путь:
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use feature qw/say/;
use File::Spec;
my $directory = shift;
opendir(my $dh, $directory);
while (my $filename = readdir $dh) {
my $fullname = File::Spec->catfile($directory, $filename); # Construct a full path to the file
next unless -f $fullname; # Only look at regular files
open my $fh, "<", $fullname;
while (my $line = <$fh>) {
if ($. == 27) {
say $fullname;
print $line;
last;
}
}
close $fh;
}
closedir $dh;
Вы также можете рассмотреть возможность использования glob
для получения имен файлов вместо из opendir
/ readdir
/ closedir
.
И если у вас есть Path :: Tiny , более простая версия:
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use feature qw/say/;
use Path::Tiny;
my $directory = shift;
my $dir = path $directory;
for my $file ($dir->children) {
next unless -f $file;
my @lines = $file->lines({count => 27});
if (@lines == 27) {
say $file;
print $lines[-1];
}
}