tags:

views:

224

answers:

2

Using File::Find, how can I pass parameters to the function that processes each file?

I have a Perl script that traverses directories in order to convert some 3-channel TIFF files to JPEG files (3 JPEG files per TIFF file). This works, but I would like to pass some parameters to the function that processes each file (short of using global variables.)

Here is the relevant part of the script where I have tried to pass the parameter:

use File::Find;

sub findFiles
{
    my $IsDryRun2 = ${$_[0]}{anInIsDryRun2};
}

find ( { wanted => \&findFiles, anInIsDryRun2 => $isDryRun }, $startDir);

$isDryRun is a scalar. $startDir is a string, full path to a directory.

$IsDryRun2 is not set:

Use of uninitialized value $IsDryRun2 in concatenation (.) or string at TIFFconvert.pl line 197 (#1) (W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables.

(The old call without parameters was: find ( \&findFiles, $startDir); )


Test platform (but production home will be a Linux machine, Ubuntu 9.1, Perl 5.10, 64 bit): ActiveState Perl 64 bit. Windows XP. From perl -v: v5.10.0 built for MSWin32-x64-multi-thread Binary build 1004 [287188] provided by ActiveState.

+6  A: 

You need to create a sub reference that calls your wanted sub with the desired parameters:

find( 
  sub { 
    findFiles({ anInIsDryRun2 => $isDryRun });
  },
  $startDir
);

This is, more-or-less, currying. It's just not pretty currying. :)

hobbs
Thanks, it worked. Is the first semicolon required (third line)?
Peter Mortensen
You don't need the that semicolon, but it doesn't hurt to have it there.
brian d foy
@hobbs => i've always liked the way Perl handles currying with anonymous subs. what would be pretty to you?
Eric Strom
+2  A: 

You can create any sort of code reference you like. You don't have to use a reference to a named subroutine. For many examples of how to do this, see my File::Find::Closures module. I created that module to answer precisely this question.

brian d foy