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

I am new to perl and would like to get a list showing the full path name from where I am searching of all my html files that had the word Expired in the file. Here is an example of what I need the output to look like:
/test.html /var/test.html /var/dir/test.html /home/test.html /home/dir/next/test.html

Replies are listed 'Best First'.
Re: Listing Files
by strat (Canon) on Mar 01, 2002 at 13:50 UTC
    You have got one or more starting directory and want to search recursively through them all for Files with the Extension .html? If you find such files that contain the word Expired, you want to write the names of these files to STDOUT.
    I think, you could do so with using the Module File::Find:
    #!/usr/bin/perl -w use strict; use File::Find; my @startdirs = qw(/home /var/dir); # list of startdirectories find ( sub { if( /\.html$/ ) { # $_ contains filename without path open (HTML, $File::Find::name) # filename with path or warn "couldn't read from $File::Find::name: $!\n"; while (<HTML>) { if ( /\bExpired\b/i ){ # if Expired found print "$File::Find::name\n"; last; # skip rest of file } # if } # while close (HTML); } # if .html }, @startdirs);

    Best regards,
    perl -le "s==*F=e=>y~\*martinF~stronat~=>s~[^\w]~~g=>chop,print"

      If you're willing to scan the filenames before scanning the contents, there's a much cleaner-looking solution:
      use File::Find; @ARGV = (); find sub { push @ARGV, $File::Find::name if /\.html\z/; }, qw(/home /v +ar/dir); while (<>) { next unless /\bExpired\b/; print "$ARGV\n"; # current filename close ARGV; # skip to next file now }

      -- Randal L. Schwartz, Perl hacker

        Thanks merlyn!
        Using @ARGV as a global List is a rather interesting idea from the perl-point-of-view, but in my eyes, strat's solution is cleaner. If you really want to list the files first and then search them for Expired, I'd do it with a closure, e.g.
        use File::Find; my @htmlFiles = (); find sub { push (@htmlFiles, $File::Find::name) if /\.html\z/; }, qw(/home /var/dir); foreach (@htmlFiles){ ...
        @merlyn: btw: thanks for the wonderful Schwartzian Transform and so many good other tricks you showed me :-)
      Thanks strat, Please explain as I am not sure why you have this at the end: I tried looking this up in my book but couldnt find what it is doing.
      }, @startdirs);
        Reply to: Re: Re: Listing Files by Anonymous Monk
        Thanks strat, Please explain as I am not sure why you have this at the end: I tried looking this up in my book but couldnt find what it is doing.
        The function find from the module File::Find expects at least two parameters:
        1. a reference to a sub
        2. a list of startdirectories (or at least one).
        E.g.
        1. find( \&wanted, $startDir );
        2. find( \&wanted, $startDir1, $startDir2 );
        3. find( sub { ... }, $startDir );
        4. find( sub { ... }, @startDirs );
        I chose construct 4.

        perldoc File::Find will give you further information.

        Best regards,
        perl -le "s==*F=e=>y~\*martinF~stronat~=>s~[^\w]~~g=>chop,print"

Re: Listing Files
by jmcnamara (Monsignor) on Mar 01, 2002 at 13:50 UTC

    Here is a non-Perl solution, if that is okay:     find . -name "*.html" | xargs grep Expired -l

    Or to have the output exactly as you specified:     find . -name "*.html" | xargs grep Expired -l | cut -c2-

    --
    John.