Использование ARGV при рекурсии по каталогам в Perl

То, что я пытаюсь сделать, это заставить мою программу рекурсивно проходить через каталог и для всех этих файлов в каталоге искать в каждом файле слово «ОШИБКА», а затем распечатывать его экземпляр в отдельном файле. Я смог сделать это, не делая его рекурсивным, то есть просто вводя, какие файлы проверять вручную в 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, чтобы программа читала каждый файл в каталоге, выполняла поиск, а затем выводила результаты поиска в файл. Надеюсь, я адекватно объяснил свой вопрос, если вам нужны какие-либо разъяснения, дайте мне знать, что сбивает с толку. Чем больше объяснений вы можете дать с ответом, тем лучше. Благодарю вас!


person user1440061    schedule 11.06.2012    source источник
comment
Вы перезаписываете свой входной файл выходным. Это кажется довольно плохой идеей, поскольку она усекает каждый найденный файл.   -  person TLP    schedule 11.06.2012
comment
А также это дубликат одного из ваших собственных вопросов: stackoverflow.com/q/10918750/725418   -  person TLP    schedule 11.06.2012


Ответы (1)


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. Вы заменяете каждый файл точной копией самого себя и заполняете массив, который никогда не используете. Я пропустил этот код из моей версии.

person ikegami    schedule 11.06.2012
comment
Он не позволяет мне использовать File::Find::Rule, он говорит, что не может найти его в @INC. Есть ли что-то, что мне нужно загрузить/добавить в мой perl, чтобы это работало? - person user1440061; 11.06.2012
comment
Он у вас установлен? Не стесняйтесь использовать File::Find, если хотите. С File::Find::Rule все проще. - person ikegami; 11.06.2012
comment
Я проверил в cmd, что у меня нет Find::File::Rule и я не могу загрузить его прямо сейчас. Могу ли я просто заменить Find::File на Find::File::Rule в коде или нужно внести другие изменения? Я новичок в этом, поэтому, пожалуйста, потерпите меня - person user1440061; 11.06.2012
comment
Я использую File::Find::Rule для создания списка имен. Вам придется сделать то же самое, используя File::Find. Вы не можете просто изменить строку использования. - person ikegami; 11.06.2012
comment
Хорошо, я потерялся... не могли бы вы помочь мне с тем, как использовать File::Find вместо File::Find::Rule? Пожалуйста, простите мое невежество - person user1440061; 11.06.2012
comment
Добавлен File::Find версии для ответа. - person ikegami; 11.06.2012
comment
Большое спасибо - извините, что продолжаю просить о все большей и большей помощи, но, похоже, вы знаете почти все! Очень ценится. - person user1440061; 11.06.2012