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

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

Hi Monks!
I need to go through large directories and search all the Perl scripts for the word "email" in them. But I cant get the command to search recursively, it works if I specify a directory, but even using "-r" it is not doing what I expected. Here is the code, if anyone would give me a better way it would be really nice.
grep -H -r "mail" mydirectory/*.pl > res/results.txt
This other code its actually better because it gives me the line number where it found the word "email", but again it cant search recursively through all directories. It would be nice if I could get with this:
find /start_dir -name *.pl -exec grep -i -H -n 'email' {} > res/resu +lts.txt\;
A file with results something like:
dir1/dir2/dir3/ file1.pl:230 email
dir_a test.pl:44 email
If anyone has done something like that and would like to share some knowledge it would help me a lot! Thanks!

Replies are listed 'Best First'.
Re: Perl and or Grep Help!
by Corion (Patriarch) on Jan 17, 2011 at 20:28 UTC

    To bring this back into the realm of Perl, see App::ack.

    Alternatively, see find2perl to convert your find command to Perl. See grep for how to search a list, and open and perlop for how to open a file and read its contents.

      Hi

      ++

      I was going to post about Ack too.

      ack --perl email mydirectory

      Should do what is needed.

      App::Ack can be installed through CPAN, or it's available as a package for many distros ("ack-grep" for Debian/Ubuntu, for example)

      FalseVinylShrub

      Disclaimer: Please review and test code, and use at your own risk... If I answer a question, I would like to hear if and how you solved your problem.

Re: Perl and or Grep Help!
by Anonyrnous Monk (Hermit) on Jan 17, 2011 at 20:48 UTC

    For one, you need to quote the *.pl, so the shell doesn't expand it.  I.e., either

    $ find /start_dir -name "*.pl" -exec grep -i -H -n 'email' {} \; > res +/results.txt

    or

    $ find /start_dir -name "*.pl" -print0 | xargs -0 grep -i -H -n 'email +' > res/results.txt

    (the -print0 / -0 combination is for when the filenames contain spaces — good habit to get into, even if they don't, for now)

Re: Perl and or Grep Help!
by rir (Vicar) on Jan 17, 2011 at 20:29 UTC
    find directory -type f -print | xargs grep "something" > outfile

    Be well,
    rir

Re: Perl and or Grep Help!
by oko1 (Deacon) on Jan 17, 2011 at 23:45 UTC

    Right, "grep" isn't going to work despite the '-r(ecursive)' switch because you've told it to only look for *.pl files in 'mydirectory/' - and no deeper than that. It's intended to either be used with '*' as the file argument, or a list of the directories that you want to look in. You're failing with "find" because you're not asking "grep" to '-l(ist)' the files it found - and possibly because you're failing to quote the metacharacters (*). Here are a couple of ways to make these work (non-Perl... I know, how horrible, right? :)

    # Search all files, then filter out the ones that don't end in '.pl' grep -Hnr mail *|grep '^[^:]*\.pl:' > results.txt # Find all .pl files and list the ones that contain 'mail' find /start_dir -name '*.pl' -exec grep -l mail {} \; > results.txt # Find all .pl files and show all the lines matching 'mail' as well as + the file path find /start_dir -name '*.pl' -exec grep -n mail {} /dev/null \; > resu +lts.txt

    The last one is an old Unix trick that's been around for a long time, but it still works quite well.

    -- 
    Education is not the filling of a pail, but the lighting of a fire.
     -- W. B. Yeats
      Thanks, it worked very well. I could also specify on this one as an example exclusion of directories I don't want it to scan right?
      find /start_dir -name '*.pl' -exec grep -n mail {} /dev/null \; > res +u +lts.txt
      find /start_dir -name '*.pl' -exec grep -n mail {} /dev/null \; > results.txt

      What is the purpose of the /dev/null? I seem to get the exact same results with and without it.

      I am trying this way, no success yet.
      find apps/ac/ -name '*.pl' -type d \( -name dirto_escape -o \) -prune +-o -print -exec grep -n sendmail {} /dev/null \; > apps/ac/grep/resu +lts.txt
Re: Perl and or Grep Help!
by rir (Vicar) on Jan 17, 2011 at 20:31 UTC
    Delete duped.
    find /directory -type f -print | xargs grep "something" > outfile

    Be well,
    rir