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

Pass an "extra' variable to Find::File subroutine Please Monks help me on this one, As described in the title, I use the Find::File module. And recursively going through directories works fine, but... I don't know how to pass an extra variable calling the subroutine. This works:
#!/usr/bin/perl -w use strict; use Find::File my $source = “/mnt/usbdisk”; sub Recursive { my ($diskpathfile = ($File::Find::name)); print $diskpathfile, “\n”; } find (\&Recursive, $source);
But this doesn't work:
#!/usr/bin/perl -w use strict; use Find::File my $source = “/mnt/usbdisk”; sub Recursive { my ($msg) = @_; print $msg, “\n”; my ($diskpathfile = ($File::Find::name)); print $diskpathfile; } find (\&Recursive(“hello”), $source);
And the trouble is, it may be simple, but I cant find a answer in the Find::File documentation itself. Can anybody give me a clue?
The great mistake is to anticipate the outcome of the engagement; Let nature take it's course, and your tools will strike at the right moment.

Replies are listed 'Best First'.
Re: Pass an "extra' variable to Find::File subroutine
by almut (Canon) on Jun 22, 2010 at 13:12 UTC

    \&Recursive is a callback function (or more precisely, a reference to it) that is being called by File::Find as it walks through the tree.  Why do you want to pass it a parameter?

    Maybe you want a closure(?)  Something like this:

    use File::Find; my $source = "/mnt/usbdisk"; sub make_wanted { my $arg = shift; return sub { my $diskpathfile = $File::Find::name; print "$arg: $diskpathfile\n"; } } find (make_wanted("hello"), $source);

    Here, make_wanted() returns a parameterized function (closure) to be used as the callback routine, i.e. the function instance retains its parameter "hello" as $arg.

      I can just guess, but that's how you pass data to callbacks in languages like C, which don't have closures.
        You'd design the C library differently.
Re: Pass an "extra' variable to Find::File subroutine
by moritz (Cardinal) on Jun 22, 2010 at 13:13 UTC
    You can just use variables from an outer scope in your callback:
    my $source = “/mnt/usbdisk”; sub Recursive { my $msg = $source; ... {
    This is the general way to handle such problems in Perl. You can abstact that away with closures:
    sub myfind { my ($code, @args) = @_; find(sub { $code->(@args)}) }

    Now you can call

    myfind \&Recursive, $source;

    And have the argument $source passed through to sub Recursive. But most likely you can solve your problem with outer lexical variables in the first place.

      As you have it (and as you say), $source would be passed to the Recursive function.  However, it's meant to be the second argument to File::Find's find function (the top-level directory to start recursing from), as that's how its API is defined.

        You are right, my mistake. If I understand the question correctly, it should actually be
        sub myfind { my ($code, $source, @args) = @_; find(sub { $code->(@args)}, $source) } myfind(\&Recursive, $source, $addtional_argument)
        Perl 6 - links to (nearly) everything that is Perl 6.
Re: Pass an "extra' variable to Find::File subroutine
by ikegami (Patriarch) on Jun 22, 2010 at 15:52 UTC

    You'll need to use globals or closures:

    # From almut sub make_wanted { my $arg = shift; return sub { my $diskpathfile = $File::Find::name; print "$arg: $diskpathfile\n"; } } my $arg = "hello"; find(make_wanted($arg), $source);
    or
    sub wanted { my ($arg) = @_; my $diskpathfile = $File::Find::name; print "$arg: $diskpathfile\n"; } my $arg = "hello"; find(sub { wanted($arg) }, $source);
    or
    my $arg = "hello"; find(sub { my $diskpathfile = $File::Find::name; print "$arg: $diskpathfile\n"; }, $source);
    or
    my $arg = "hello"; sub wanted { my $diskpathfile = $File::Find::name; print "$arg: $diskpathfile\n"; } find(\&wanted, $source);