Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
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
Replies are listed 'Best First'.
Re: File::Find: Return array of "wanted" files
by choroba (Canon) 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.

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 (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, );

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 drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2015-07-30 04:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (269 votes), past polls