in reply to Listing Files

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"

Replies are listed 'Best First'.
•Re: Re: Listing Files
by merlyn (Sage) on Mar 01, 2002 at 15:19 UTC
    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 :-)
        But setting @ARGV is an acceptable way to prepare for a diamond walk. With your solution, you have to either copy @htmlFiles to @ARGV, or do your own open loop, thereby moving further and further from idiomatic Perl.

        Feel free to do what you want in the privacy of your own cubicle, but I'd definitely ding you with a yellow flag in a formal code review for not using @ARGV in some manner in that loop.

        -- Randal L. Schwartz, Perl hacker

Re: Re: Listing Files
by Anonymous Monk on Mar 01, 2002 at 16:24 UTC
    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"

        Thanks!