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

Hi, I'm using file::find to perform a recursive copy. I would like to pass arguments to the wanted subroutine to trigger the appropriate copy behavior (overwrite or ignore if already present). The presence of arguments seems to interfere with File::Find functionality though. I can get around this by using global variables but this seems messy. Is there a clean way to pass args to the subroutine? Thanks for your help!
  • Comment on Passing arguments to wanted subroutine in File::Find

Replies are listed 'Best First'.
Re: Passing arguments to wanted subroutine in File::Find
by thospel (Hermit) on Oct 02, 2004 at 21:52 UTC
    In perl you can solve the arguments to a callback problem by using a closure:
    sub foo { my $arg1 = ....; my $arg2 = ....; find({ wanted => sub { wanted($arg1, $arg2) }, ...}); }
Re: Passing arguments to wanted subroutine in File::Find
by Zaxo (Archbishop) on Oct 02, 2004 at 21:53 UTC

    It's true that globals are messy, but that is the way File::Find works. To avoid unexpected behavior with lexical closures, I declare the globals with use vars qw/. . ./; to place them in the symbol table and satisfy strict.

    It sounds as if your uses for this are mainly as configuration flags which will not be changed during a run. That is pretty manageable as global variables go.

    Update: ++thospel's solution takes advantage of lexical closures to place a wrapper around the find call. Very elegant!. Added: On second look, I think that solution may still have difficulty with closures taking on unexpected values. Localizing the variables may be preferable. Test before you leap.

    After Compline,
    Zaxo

Re: Passing arguments to wanted subroutine in File::Find
by shenme (Priest) on Oct 02, 2004 at 22:06 UTC
    Some people do this using closures to parameterize the wanted() subroutine.
    use File::Find (); look_for_this_ext( 'pl', '.' ); sub look_for_this_ext { my $this_ext = shift; my $this_tree = shift; my $wanted = sub { # print " I see '$_'\n"; print " '$_'\n" if /\.${this_ext}\z/; }; File::Find::find( { bydepth => 1, no_chdir =>1, wanted => $wanted, }, $this_tree, ); } __END__ './anony001.pl' './anony002.pl' './jmw1.pl' './liz.pl' './template0.pl' './demerphq/treap.pl'
•Re: Passing arguments to wanted subroutine in File::Find
by merlyn (Sage) on Oct 03, 2004 at 15:52 UTC