Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Using File::Find to Create a List of Files

by svsingh (Priest)
on May 16, 2003 at 15:59 UTC ( [id://258690]=perlquestion: print w/replies, xml ) Need Help??

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

I'm trying to write a script that will find all files with a specific extension (.hhc in my case) under the current directory. I have some basic code working, but it's not quite what I want and I'm not sure where to go from here. I'm not having much luck with the documentation or Cookbook examples.

Here's the code so far...

use strict; use File::Find; use Cwd; # BEGIN MAIN $, = "\n"; print &getFileList; # END MAIN sub getFileList { my @fileList = (); # list for matching files find(\&findFilter, "."); # populates the list return @fileList; sub findFilter { if ( /\.hhc$/ ) { # only push matching filenames my $curDir = cwd; my $fileName = $curDir . $_; push @fileList, $fileName; } return; } }

Here are my questions and issues:

  1. I'm getting a warning about using @fileList in the sub-subroutine. I know that's bad form, but I couldn't figure out a better way to do this. Is there a better way?
  2. I'd like to extract paths relative to the starting directory. I tried to do this by passing cwd from getFileList to findFilter. However, whenever I pass parameters to fileFilter, it seems to lose the file from $_. Is there a way to pass arguments into fileFilter?

I had to do a lot of digging to get enough information to get this far and really appreciate any help you can offer. I'm also hoping this can serve as a useful example in case anyone else is trying to do the same thing. For example, this can also be a good way to create an MP3 playlist.

Thanks for your help everyone.

Replies are listed 'Best First'.
Re: Using File::Find to Create a List of Files
by broquaint (Abbot) on May 16, 2003 at 16:08 UTC
    1. I'm getting a warning about using @fileList in the sub-subroutine. I know that's bad form, but I couldn't figure out a better way to do this. Is there a better way?
    Use an anonymous sub instead of a nested sub (see. tilly's Re (tilly) 9: Why are closures cool? for more info on why they aren't always safe) e.g
    sub getFileList { my @fileList = (); # list for matching files my $findFilter = sub { if ( /\.hhc$/ ) { # only push matching filenames my $curDir = cwd; my $fileName = $curDir . $_; push @fileList, $fileName; } return; }; find($findFilter, "."); # populates the list return @fileList; }
    2. I'd like to extract paths relative to the starting directory. I tried to do this by passing cwd from getFileList to findFilter. However, whenever I pass parameters to fileFilter, it seems to lose the file from $_. Is there a way to pass arguments into fileFilter?
    You may very well just want to use $File::Find::name instead of constructing it yourself.

    As always TIMTOWTDI

    use File::Find::Rule; my @files = find( file => name => '*.hhc', dir => '.' );
    See. File::Find::Rule for more info.
    HTH

    _________
    broquaint

      The anonymous sub works perfectly. Thank you very much.
Re: Using File::Find to Create a List of Files
by grantm (Parson) on May 16, 2003 at 20:36 UTC

    It looks like you have your problem solved but you may be interested in an alternative solution:

    use strict; use File::Find::Rule; use Cwd; $, = "\n"; print File::Find::Rule->file()->name( '*.hhc' )->in( cwd );
Re: Using File::Find to Create a List of Files
by freddo411 (Chaplain) on May 16, 2003 at 16:58 UTC
    Hi, You've got the basic idea correct. I also wrote some perl to perform a similar function. I also played loose with the rules by making use of global vars to store the matches. Here's my complete code:

    #!/usr/bin/perl ######### # # index.pl # # script to create a static HTML file listing all pdfs down # from a particular directory and provide links to them. use Template; use File::Find; use File::Basename; # Template Files my $tmpl_dir = "/export/home/fredk/docs/index/templates"; my $output_tmpl = "$tmpl_dir/pdf.tmpl"; # Name of Output file $outputFile = "pdfs.html"; # Declarations my @list; # Extract the path to this script my $dir = dirname($0); if ( $ARGV[0] ) { $dir = $ARGV[0]; } # OR, override it by the cmd lin +e # What to search for CURRENTly hard coded #my $regex = '.*\.html$'; my $regex = '.*\.pdf$'; # Create a list "@list" containing the path of the pdfs &find(\&wanted, $dir); # # Output HTML my $vars = { # change to be appro. for the form 'list' => \@list, }; my $template = Template->new(); $template->process( $output_tmpl, $vars, $outputFile) || &error( $template->error()) ; exit; ##################################### # # The wanted() function does whatever verifications you want. # $File::Find::dir contains the current directory name, and $_ # the current filename within that directory. # $File::Find::name contains "$File::Find::dir/$_". You are # chdir()'d to $File::Find::dir when the function is called. # The function may set $File::Find::prune to prune the tree. sub wanted { if ( /$regex/ ) { push( @list, $File::Find::name); } }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://258690]
Approved by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (6)
As of 2024-04-19 12:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found