r.joseph has asked for the wisdom of the Perl Monks concerning the following question:

Ok, File::Find works great. But is there a better way to do the below?
find(\&wanted,$root); sub wanted { if (/\.(\w*)/) { foreach (@exts) { if (lc($1) eq $_) { print $File::Find::dir,"/",$hold,"\n"; } } } }
As you can see, the 'wanted' sub is much to...bloated. There must be a better way. I am stupid, I know, so thanks for all the help! R.Joseph

Replies are listed 'Best First'.
Re: Better way to search?
by chromatic (Archbishop) on Jan 05, 2001 at 06:08 UTC
    Use a hash.
    my %exts; @exts{@exts} = (); sub wanted { if (/\.(\w+)/) { print "$File::Find::dir/$hold\n" if exists $exts{lc($1)}; } }
    grep would also do.

    This is untested, but the implementation can't be too far different.

      If you really wanted to do away with "bloat", you could condense chromatic's example further ...

      sub wanted { print "$File::Find::dir/$hold\n" if /\.(\w+)$/ and exists $exts{ lc $1 }; }

      ... which reads a little more natural (at least to me :-)).

      You might also consider adding a small snippet of code so directories with multiple matches are only printed once instead of once per match.

      my %already_seen; sub wanted { print "$File::Find::dir/$hold\n" if /\.(\w+)$/ and exists $exts{ lc $1 } and not $already_seen{ $File::Find::dir }++; }

          --k.


        It's a hash slice.

        It fills the hash %exts with the contents of your @exts array. The keys are set to the values in @exts, and the values in the hash are set to undef. That's why you need to test for exists rather than "truth"; because the values aren't "true", but the keys do exist.

Re: Better way to search?
by chipmunk (Parson) on Jan 05, 2001 at 06:40 UTC
    Use a regex. :)
    $ext_re = '\.(?:' . join('|', @exts) . ')$'; find(\&wanted, $root); sub wanted { if (/$ext_re/o) { print "$File::Find::dir/$hold\n"; } }
    The $ anchor is important if your filenames can contain multiple periods.