Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

File::Find: Return array of "wanted" files

by alpha-lemming (Novice)
on Oct 04, 2013 at 07:15 UTC ( #1056844=perlquestion: print w/ replies, xml ) Need Help??
alpha-lemming has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Monks, I am using File::Find in a loop to recursively search a list of direcories and grep the found files for a specific pattern. I can print out the matching files, but what I really want to do is store a the list in an array. Here's what I've done so far:
sub findstuff { my $file = $File::Find::name; return unless -f "$file"; if (fgrep { /regex/ } "$file") { print "Found regex in $file\n"; } } foreach (@dirs) { find(\@findstuff, $_); }
How can I get list of matching files into an array inside of the foreach loop? Thanks!

Comment on File::Find: Return array of "wanted" files
Download Code
Re: File::Find: Return array of "wanted" files (File::Find::Rule)
by Anonymous Monk on Oct 04, 2013 at 07:23 UTC

      AFAIK, the OP wanted to apply the regex to the contents of the files, not the names, so it should be:

      my @files = File::Find::Rule->grep( qr/regex/ )->in( @dirs );

        AFAIK, the OP wanted to apply the regex to the contents of the files, not the names, so it should be:

        Go figure, I thought it was a typo, oh well :)

        use File::Find::Rule qw/ find /;
        my @files = find( file => grep => qr/regex/, in => \@dirs, );

Re: File::Find: Return array of "wanted" files
by keszler (Priest) on Oct 04, 2013 at 07:44 UTC
    Because File::Find's "wanted function" does not return the file names, the array that will hold the matching files needs to be in scope, e.g. a package or global variable.

    Note: File::Find's find function takes an array as its 2nd parameter, so foreach (@dirs) isn't needed.

    use strict; use warnings; use File::Find; my @files; my @dirs = qw(/some /list /of /dirs); sub findstuff { my $file = $File::Find::name; return unless -f "$file"; if (grep { /regex/ } "$file") { print "Found regex in $file\n"; push @files, $file; } } find(\&findstuff, @dirs); print "Results:\n@files\n";
    Update: Interesting: I interpreted the OP's if (fgrep { /regex/ } "$file") as a typo (fgrep vs grep) for a check for a regex in the filename. choroba's response below makes better sense of that.
Re: File::Find: Return array of "wanted" files
by choroba (Abbot) on Oct 04, 2013 at 07:44 UTC
    Several issues:
    • There is no fgrep command in Perl or File::Find. You have to implement it yourself.
    • The "wanted" function (findstuff in your code) is run in the directory where the file resides, not from the top one. The -f test must be run against $_, not $File::Find::name.

    Use push to add a member to an array. Here is my attempt to implement what you wanted:

    #!/usr/bin/perl use strict; use warnings; use File::Find; sub fgrep { my ($regex, $file) = @_; open my $FH, '<', $file or die $!; while (<$FH>) { return 1 if /$regex/; } return 0; } my @found; sub findstuff { my $file = $_; return unless -f $file; my $fullpath = $File::Find::name; if (fgrep(qr/regex/, $file)) { push @found, $fullpath; } } my @dirs = @ARGV; # Populate @dirs. find(\&findstuff, @dirs); print "@found\n";

    Update: push added.

    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Thanks.

      FWIW, I was using fgrep from File::Grep. I should have included the "use" lines for clarity.

      I actually didn't realize that I can push to @found from within the sub. Guess I better read up some more on scope..

        The scope of a lexical is going from where the lexical is declared to the end of the enclosing block. In the case of @found above, to the end of the file.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1056844]
Approved by hdb
Front-paged by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2014-10-25 09:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (142 votes), past polls