我有一个程序的结果,它给了我一些搜索的结果,给了我2000多个文件的txt档案。我只需要在每个文件中加入一行特定的内容,这是我一直在用Perl尝试的。
opendir(DIR, $dirname) or die "Could not open $dirname\n";
while ($filename = readdir(DIR)) {
print "$filename\n";
open ($filename, '<', $filename)or die("Could not open file.");
my $line;
while( <$filename> ) {
if( $. == $27 ) {
print "$line\n";
last;
}
}
}
closedir(DIR);
但是第5行的$filename有问题,我不知道有什么办法可以替代它,这样我就不用手动命名每个文件了。
先谢谢你。
这段代码有几个问题。
用一个老式的裸词标识符来表示目录句柄 而不是像你一样用一个自动变量来表示文件句柄。
在文件名和文件句柄上使用同一个变量是非常奇怪的。
在尝试打开文件之前,你没有检查该文件是一个目录还是其他什么东西,而不是一个普通的文件。
$27
?
你从来没有给那个 $line
变量在打印前。
除非 $directory
是你的程序的当前工作目录,你遇到了一个在 readdir
文件
如果你打算从一个readdir中对返回值进行文件测试,你最好把相关的目录前缀。否则,因为我们没有把chdir放在那里,就会测试错误的文件。
(用open代替filetest)
总是 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];
}
}