我想编写一个从目录树顶部开始的Perl脚本(在命令行参数中提供),并递归遍历每个子目录,对每个文件执行特定操作。
我正在使用finddepth
,但是当我在基本目录中两级或更多级别的目录上运行脚本时,它似乎不起作用。
这是我的代码:
#!/usr/local/bin/perl -w
use strict;
use File::Copy;
use File::Find;
use File::Basename;
use File::Path;
finddepth(\&file_list, @ARGV);
sub file_list {
my ($file_path, $name, $path, $suffix);
$file_path = $File::Find::name;
($name, $path, $suffix) = fileparse($file_path, /\.*/);
my $fullname = $name . $suffix;
my $file = $fullname;
if ($file =~ /^[^\.].*[^\.pl]$/) {
copy($file, "$file.orig");
open(FILE, "$file");
my @file_data = <FILE>;
close(FILE);
open(FOUT, ">$file") or die " \n File cannot be opened !";
foreach my $line (@file_data) {
if ($line =~ /^\s+Error:/) {
$line =~ s/([^-]\d+)/ \*\*/gc;
print FOUT $line;
}
else {
print FOUT $line;
}
}
close(FOUT);
}
}
始终抛出以下警告/错误:
我似乎无法弄清楚为什么会这样。我试图让我的问题尽可能具体。如果您需要更多信息,请与我们联系。谢谢。
答案 0 :(得分:1)
您无法打开该文件,因为$file
恰好是该时间点的目录,因此您需要为此添加检查。
打开文件进行阅读时,可能需要添加or die
语句。
另请注意,File::Find
将$_
设置为当前文件名,因此您生成$file
所用的5行实际上是不必要的。
答案 1 :(得分:1)
您的代码存在一些问题。
use warnings
优于命令行-w
在第一个使用点声明变量,而不是在子程序顶部的块中声明
使用open
的三参数形式和词汇文件句柄
检查open
来电的状态时,请将内置变量$!
放入die
字符串中,以便了解为什么开放失败
不要将标量变量放在双引号内。这可能是不必要的,在某些情况下可能会破坏您的代码。你不太可能做任何你想做的事情
此程序的重写使用use autodie
来避免使用显式open ... or die $!
语句。它使用rename
来更改文件的名称,而不是复制它并覆盖原始文件。
我没有将整个文件读入内存,而是打开重命名的文件并逐行读取,编辑并将每一行写入新文件
我已经写过它以便忽略以点开头或以.pl
结尾的文件 - 我希望这是对的。我也非常怀疑你的替换s/[^-]\d+/ **/g
,它寻找一个数字序列,前面是一个不是连字符的字符;是吗?
#!/usr/local/bin/perl
use strict;
use warnings;
use autodie;
no autodie 'unlink';
use File::Find 'finddepth';
finddepth(\&file_list, @ARGV);
sub file_list {
return unless -f;
return if /^\./ or /\.pl$/;
my $file = $_;
my $orig = "$file.orig";
unlink $orig;
rename $file, $orig;
open my $infh, '<', $orig;
open my $outfh, '>', $file;
while (my $line = <$infh>) {
if ($line =~ /^\s+Error:/) {
$line =~ s/[^-]\d+/ **/g
}
print $outfh $line;
}
close $outfh;
}