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

HI, I'm trying to create a programme that will enable the user to specify a directory to search in and then allow them to search all files in that directory for akey phrase. Thus far I've managed to list all files in a directory, but I found that perl only searches the directory that the .pl file is located in, whereas I want the user to be able to input a directory to be searched in. I can find code to search a file or print files in a directory,but not to search all files in a specified directory. This is burning my brains or rather brain as I only have one, as I'm a complete perl novice..
  • Comment on searching several files for a string at one time

Replies are listed 'Best First'.
Re: searching several files for a string at one time
by Corion (Patriarch) on May 06, 2010 at 09:23 UTC

    You don't show any (relevant) code, so I have to guess where your problem could lie. See perlvar on @ARGV and/or Getopt::Long for how to parse command line switches. Also see opendir and readdir or Path::Class for how to list files in one directory. See File::Find for how to find files below a given directory. Alternatively see App::Ack for a reimplementation of the grep program in Perl.

Re: searching several files for a string at one time
by moritz (Cardinal) on May 06, 2010 at 09:38 UTC
    Depending on your actual problem, App::Ack might solve it for you. It can traverse directories recursively, search for patterns and strings, and comes with lots of optional bells and whistles.
Re: searching several files for a string at one time
by JavaFan (Canon) on May 06, 2010 at 09:45 UTC
    There's a utility that does that, and existed and matured even before Larry came up with the idea to create Perl. It's called "grep". Use it. "Code reuse" doesn't stop at the CPAN border.
Re: searching several files for a string at one time
by daggy (Novice) on May 06, 2010 at 09:39 UTC

    this is the code I've been using

    @files = <*>; foreach $file (@files) { print $file . "\n"; }

    You can include any path in your filesystem between the <> marks. For example, say your web site is in the /var/www/htdocs/ directory and you want a list of all the files:

    @files = </var/www/htdocs/*>;

    Or if you just want a list of the files with the extension .html:

     @files = </var/www/htdocs/*.html>;

    however, where it says I can include any path, it doesn't work as it still only lists the directory that the .pl file is in Sorry for notposting the code :)

      I forgot a very simple function that you might want to use to replace <...>: File::Glob::bsd_glob - it works just like <...> but it accepts the directory to glob as a parameter and understands whitespace in directory names.

Re: searching several files for a string at one time
by daggy (Novice) on May 06, 2010 at 10:41 UTC
    Is there a general consensus on whether glob or grep is better for what I want to achieve? I can't seem to find how to make glob search multiple files for a string... for example, say I want to find files with the word 'monk' in them in my documents.. is it possible to do this? Thanks for the help

      glob and grep complement each other. glob is for finding filesystem entries (think "names"), and grep is for searching lists (like lines in a file). If you don't use the grep command line utility, then your Perl program will need to combine both. Use bsd_glob to find the files that are of interest, and then use grep to find the lines in those files.

        So the correct procedure would be to ask the user to specify the directory they wish to search in

        Use Glob to list all files in the directory? Or should I use glob to search for 'monk' and glob would bring back a list of files with 'monk' in them?

        then use Grep to specify which lines the word 'monk' is on?

        What is bsd_glob..

        Sorry for the completely noob like comments, but I'm a complete noob so it's to be expected.
Re: searching several files for a string at one time
by daggy (Novice) on May 06, 2010 at 19:32 UTC

    Hey, update here This is how far I've got so far

    #!/usr/bin/perl use strict; use warnings; my $directory = 'C:\Users\Anthony\music'; opendir (DIR, $directory) or die $!; while (my $file = readdir(DIR)) { print "$file\n"; } closedir(DIR);

    This lets me open any directory, but how do I make it so the users can select the directory when the programme is ran? Also, I found this code, whcih appears to do what I want, but I can't seem to merge it with what I already have

    $ grep "redeem reward" /home/tom/*.txt
      but how do I make it so the users can select the directory when the programme is ran?
      One way is to pass it in on the command line (see shift):
      use strict; use warnings; my $directory = shift; print "dir=$directory\n"; # just for debug

      Run your program as:

      $ ./838783.pl /foo/bar dir=/foo/bar
        I tried the first paragraph of code
        use strict; use warnings; my $directory = shift; print "dir=$directory\n"; # just for debug
        I got this error use of uninitilised value $directory in concatenation (.)or string at.......... sayingline 6 fault in code, but dont know why... bah this stuff confuses me Do I add the code you posted to the code I already have or is it stand alone? If so, what did you mean by run my file as the second bit of code?