在Perl中通过目录递归时使用ARGV

时间:2012-06-11 16:11:10

标签: perl argv

我要做的是让我的程序通过一个目录递归,并为目录中的所有文件搜索,搜索每个文件中的单词“ERROR”,然后在一个单独的文件中打印出它的实例。我能够在不进行递归的情况下执行此操作,即只需输入要在cmd中手动检查的文件。我想知道在递归时使用ARGV的正确方法是什么。这是我到目前为止的代码:

#!/usr/bin/perl
use strict;
use warnings;
use File::Find;

my $dir = "c:/programs";

find(\&searchForErrors, $dir);

sub searchForErrors()
{
my $seen = 0;

if (-f){
    my $file = $_;
    my @errors = ();

    open FILE, $file;
    my @lines = <FILE>;
    close FILE;

    for my $line (@lines){
        if (/ERROR/ ){
        push(@errors, "ERROR in line $.\n");
        print FILE "ERROR in line $.:$1\n" if (/Error\s+(.+)/);
    }
    open FILE, ">$file";
    print FILE @lines;
    close FILE;
    }
}
}

我需要知道的是如何合并ARGV以便程序将读入目录中的每个文件,执行搜索,然后将搜索结果输出到文件。我希望我已经充分解释了我的问题,如果你需要任何澄清,请告诉我什么是令人困惑的。你可以用答案给出的解释越多越好。谢谢!

1 个答案:

答案 0 :(得分:4)

ARGV通常用于迭代从Perl外部提供的文件。

 $ find -type f --exec perl script.pl {} +

 # script.pl
 while (<>) {
     print "$ARGV:$.: $1\n" if /Error\s+(.+)/;
 } continue {
     close(ARGV) if eof;  # Reset $.
 }

但这没有必要。你也可以这样做:

 use File::Find::Rule qw( );

 @ARGV = File::Find::Rule->file->in('.');
 while (<>) {
     print "$ARGV:$.: $1\n" if /Error\s+(.+)/;
 } continue {
     close(ARGV) if eof;  # Reset $.
 }

我更喜欢File::Find::Rule,但如果您将上述代码段与以下代码段进行比较,您可以坚持使用File::Find,原因应该很明显:

use File::Find qw( find );

@ARGV = ();
find({ wanted => sub { push @ARGV, $_ if -f }, no_chdir => 1 }, '.');

 while (<>) {
     print "$ARGV:$.: $1\n" if /Error\s+(.+)/;
 } continue {
     close(ARGV) if eof;  # Reset $.
 }

PS - 您正在用自己的精确副本替换每个文件,并且您正在填充一个您从未使用过的数组。我从我的版本中省略了该代码。