http://qs321.pair.com?node_id=1031162

amma has asked for the wisdom of the Perl Monks concerning the following question:

I created a array of filehandles like below

my @handles = map { open my $fh, '<', $_; $fh } @files;

Now I want to open each file with file handle and search for a particular pattern and store that file name when pattern is succesful

any initial code that would help me is appreciated

Replies are listed 'Best First'.
Re: Array of filehandles
by kcott (Archbishop) on Apr 29, 2013 at 08:11 UTC

    G'day amma,

    That's probably not the best way to go. You have no error checking so you won't know which file handles in @handles are actually opened. The association between filename and file handle is through an index which is assumed to be common. You've shown no reason why you want to generate an array of file handles.

    You haven't shown sufficient context to provide more than a rough answer; however, I think code like this would probably be a better solution:

    ... for my $file (@files) { open my $fh, '<', $file or die $!; while (<$fh>) { if (/a particular pattern/) { print "Pattern found in $file\n"; last; } } close $fh; } ...

    If you have a legitimate requirement to use the code you posted, then you'll need something closer to this:

    ... my @handles = map { open my $fh, '<', $_; $fh } @files; for my $index (0 .. $#files) { next unless $handles[$index]->opened(); while (<$handles[$index]>) { if (/a particular pattern/) { print "Pattern found in $files[$index]\n"; last; } } } close $_ for grep { $_->opened() } @handles; ...

    -- Ken

Re: Array of filehandles
by Rahul6990 (Beadle) on Apr 29, 2013 at 07:06 UTC
    Hi, I would prefer

    my @matching_file; foreach $file (@file_list) { open (my FH, '<', $file); while(<FH>) { if(/<your pattern>/) { push(@matching_file,$file); #Store files in which pattern is pres +ent. last; #Once the pattern is found no need to iterate further the +same file. } } }
Re: Array of filehandles
by hdb (Monsignor) on Apr 29, 2013 at 07:04 UTC

    If you want the filenames and not the handles for the files that match the pattern, it is better to operate on the filenames and not the handles. If you want the handles, my code can be modified easily: just pass in the handles and remove the open statement.

    use strict; use warnings; use autodie; sub findpattern { my $file = shift; my $pattern = shift; open my $fh, '<', $file; while(my $line=<$fh>){ return 1 if $line =~ /$pattern/; } return 0; } my @files = <*.pl>; my @success = grep { findpattern( $_, "Data::Dumper" ) } @files; print join "\n", @success, "\n";
Re: Array of filehandles
by Krambambuli (Curate) on Apr 29, 2013 at 07:43 UTC
    You could try as well something like

    my %handles = map { open my $fh, '<', $_; $fh => $_ } @files;

    and further use keys %handles instead of @handles, and then the filename is $handles{$fh}.

Re: Array of filehandles
by Anonymous Monk on Apr 29, 2013 at 07:45 UTC

    any initial code that would help me is appreciated

    Where did you get that code that you have? Have you read perlintro?

    You have already opened the files, that's what filehandles are, doors to the file, all you have to do is read from them :) perlintro explains opening/reading files, and simple pattern matching

Re: Array of filehandles
by pachydermic (Beadle) on Apr 29, 2013 at 13:50 UTC

    This might not be what you're looking for, but could help you do something similar - the benefit of this is that it's extremely quick and easy. While I like Perl's regex a lot, for this kind of thing I usually use a unix command like:

    grep -r -l -I -s THINGTOSEARCHFOR DIRECTORYTOLOOKIN | cut -d: -f1

    For which I have an alias in my .cshrc:

    alias scour 'grep -r -l -I -s \!:1 \!:2 | cut -d: -f1'

    The syntax is "scour thingtosearchfor directorytolookin".

    To search every file in a directory (recursively) for a particular grep argument. Comes in handy sometimes. With the current options it just outputs the filenames, but you could easily tweak that.