in reply to Adding a dispatch table and getting "Variable $x will not stay shared" errors.

I second using a Getopt::* module, but to comment on your code, you are passing @args to findfile(), but not using it as proper function argument (you probably mean $_[0] instead of $args[0] in the findfile() function).

Also, there's no point in having named nested subroutines. Instead of \&wanted, just use an anonymous subroutine...but File::Find doesn't work like what you are trying to do anyway. you shouldn't try to return things from your wanted function (find() doesn't return anything useful), you might set a variable in an outer scope though.


So here's my untested rewrite:
sub findfile { my $target = $_[0]; my $location = "/tmp/dir1"; my $foundfile; $target = qr/$target/; my $filename = find(sub { ($foundfile = $File::Find::name) if $File::Find::name =~ $targ +et; }, $location); print $filename; }
But even with this, do you really want to search all subdirectories of /tmp/dir1 with find()? Or is -f "$location/target" what you want? Is "$target" supposed to be a regular expression? Or just the file basename (in which case you would want "if $_ eq $target" in the function)?

Update: Oops. I removed the accidentally left in "return $foundfile".

Replies are listed 'Best First'.
Re^2: Adding a dispatch table and getting "Variable $x will not stay shared" errors.
by gctaylor1 (Hermit) on Mar 03, 2009 at 02:02 UTC
    • "But even with this, do you really want to search all subdirectories of /tmp/dir1 with find()? "
      - Well, (he says hesitatingly) I think I do. What I do in my real script is have a hash tied to a part of the regex ($target in this script) that gets me closer to where I want to look($location) for the regex filename. Even then it has to search through several hundreds of files before finding the right one. When it finds the right file it captures the name and path for later use. Are you thinking I'm not using find() correctly?
    • "Or is -f "$location/target" what you want?"
      - I know for sure I don't want to include the $location in the $target on my command line. Part of my reason for using find() is to be able to find the path for me by descending in to directories. So my command line would be something like
      $ script.pl -f test.txt
      and the end result is where in the directory structure test.txt is located.
    • "Is "$target" supposed to be a regular expression?"
      - It's a regex.
    • "Or just the file basename (in which case you would want "if $_ eq $target" in the function)?"
      Ok, so you do want to descend into sub-directories. But File::Find doesn't easily let you stop searching when you've found your file, so you could either use something like File::Next, or wrap the call to find() in an eval {} block, and die when you've found the file. Something like:
      eval { find(sub { ($foundfile = $File::Find::name) if $File::Find::name =~ $target; die "FoundFile" if $foundfile; }, $location) }; die $@ if $@ and $@ !~ /FoundFile/;