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

I was fiddling around with File::Find and was finally able to get what I wanted using strict and warnings but am not sure if my methods are sound. If there are better ways to do the same thing, I'd like to learn.

I created a generalized sub in order to make repeated searches with different arguments, as it doesn't make sense to create separate wanted subs for each search.

The parts I'm particularly suspicious about are:

Also, I would like to learn a little about the statement:

*name = *File::Find::name;
if someone could direct me what to look it up under. Thanks for your time.
use strict; my @found_files = Search_File('c:/Documents and Settings','udefdown.lo +g'); foreach (@found_files) { print "found: '$_'\n"; } sub Search_File { use File::Find (); # for the convenience of &wanted calls, including -eval statements: use vars qw/*name/; *name = *File::Find::name; our ($start_path, $search_name) = @_; our @matching_files = (); if ($search_name) { # Traverse desired filesystems File::Find::find({wanted => \&wanted}, $start_path); } return @matching_files; sub wanted { /^$search_name\z/si && push(@matching_files, $name); } }

"640K ought to be enough for anybody." -- Bill Gates, 1981

Replies are listed 'Best First'.
Re: Fiddling with File::Find
by merlyn (Sage) on Oct 05, 2001 at 01:12 UTC
    You really want an anon subroutine, not a nested named subroutine (which isn't even permitted really anyway).
    sub Search_File { require File::Find; my ($start_path, $search_name) = @_; my @matching_files = (); if ($search_name) { # Traverse desired filesystems File::Find::find(sub { /^$search_name\z/si && push(@matching_files, $name); }, $start_path); } return @matching_files; }
    And now it's even backward compatible to the version of Perl my ISP is running (5.5.3).

    -- Randal L. Schwartz, Perl hacker

      If I paste your snippet into a sample program strict complains about $name not being defined. If I include the two statements:
      use vars qw/*name/; *name = *File::Find::name;
      it works, but I get a warning message: Name "File::Find::name" used only once: possible typo at search.pl line 12 What is the proper way to define $name when using strict and warnings so that no messages are generated?

      "Whether you think that you can, or that you can't, you are usually right." -- Henry Ford

        Use those lines *before* you use warnings. It's a rather spurious warning, but hard to smack down in the source code.
        Sorry. I snipped your snippet in haste. Change $name to $File::Find::name. As for the warning, this is one of those times when the warning is a warning, but not really doing anything wrong. That's why I don't code "warning-free" occasionally.

        -- Randal L. Schwartz, Perl hacker

(jeffa) Re: Fiddling with File::Find
by jeffa (Bishop) on Oct 05, 2001 at 01:20 UTC
    Here is my Cookbook influenced solution.
    use strict; use File::Find; use Getopt::Std; use vars qw(%opts); getopts('d:n:',\%opts); my ($dir,$name) = @opts{qw(d n)}; USAGE() and exit unless $dir and $name; find sub { print "$_\n" if /$name/ }, $dir; sub USAGE { print "USAGE: $0 -d dir -n filename\n" }

    i like merlyn's better though :)

    (slight update - removed one silly line)

    jeffa