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

I need to search for a specific piece of text in all files in a directory. Since I also need to do this recursively I want to use File::Find.

I can return file names easily. What I need to do, though, is to search for the pattern then only print out those files which have the pattern in it. I don't want to do anything to the files; I just want a list returned.

I know it's simple but for some reason I have thrown up a brick wall.

I'm assuming (I know that can be dangerous) that I would need to do an open(FH, $file) on each file returned then search for the pattern then.

Am I even on the right track?

Thanks.

Replies are listed 'Best First'.
Re: text search in a file
by shemp (Deacon) on Aug 10, 2005 at 21:55 UTC
    Update:I had the args to grep backwards
    I dont know what else you'll need to do with the info, since you said that you're going to print out the filenames, if you're on a *nix system you could just:

    grep -Rl <basedir> <string to macth>

    grep -Rl <string to macth> <basedir>
    The 'R' switch is grep recursive, and the 'l' switch is to have grep only output the filenames with matches, instead of the full lines.

    I use the most powerful debugger available: print!
      other way around (man grep for the switch details):
      grep [options] PATTERN [FILE...]
      Unfortunately, not all greps have a recursive flag, such as /usr/bin/grep on Solaris. :( I'm forced to create my own recursive grep like this:
      grep -li search_term * */* */*/* */*/*/* (etc.)
      But I agree that a recursive grep is the best solution for the OP.

        Nah - much easier to do something like:

        grep -li search_term `find . -type f`
        Assuming there aren't so many files that you exhaust the command shell line length. Or you can check out xargs, or even -exec option on find.

        TMTOWTDI - even in shell. :-)

        Or if you use the most spiffy zsh you can do this:

        grep -li search **/*(.)

        Which will recursively search only files. But again that may bump into a number of arguments limitation (in which case you'd use print -N **/*(.) | xargs grep -li search or the like).

        --
        We're looking for people in ATL

      Sheesh. *cough*

      Boy is *my* face red.

      I was so caught up in using perl I completely forgot about grep.
      That does exactly what I need.

      Thanks muchly.

Re: text search in a file
by sgifford (Prior) on Aug 10, 2005 at 22:23 UTC
    A straightforward way to do this is write a wanted sub to search for the pattern, and if it matches append the current filename to an array.

    Here's an example:

    #!/usr/bin/perl use warnings; use strict; use File::Find; use FileHandle; # Pattern is first argument; # remaining arguments are file or directory names. # Default directory is '.' my $pat = shift; my @results; # Do the search find(patternfinder(qr/$pat/,\@results), @ARGV?@ARGV:'.'); # Print the results print join("\n",@results),"\n"; sub patternfinder { # Generate a sub to search for a pattern and save the results my($pattern,$result) = @_; # Anonymous sub in a closure return sub { my $fh = new FileHandle $_, "r" or return warn "Couldn't open '$File::Find::name': $!\n"; # Search for pattern, and add to array if it matches. while (<$fh>) { if (/$pattern/) { push(@$result,$File::Find::name); return; } } close($fh) or return warn "Couldn't close '$File::Find::name': $!\n"; } }
Re: text search in a file
by gellyfish (Monsignor) on Aug 10, 2005 at 21:53 UTC

    A suggestion would be to look at the code of the NMS Simple Search which does exactly this.

    /J\