2010-01-13 6 views
13

Usando File::Find, ¿cómo puedo pasar parámetros a la función que procesa cada archivo?¿Cómo paso parámetros a la subrutina File :: Find que procesa cada archivo?

Tengo un script de Perl que atraviesa directorios para convertir archivos de 3 canales TIFF a archivos JPEG (3 archivos JPEG por archivo TIFF). Esto funciona, pero me gustaría pasar algunos parámetros a la función que procesa cada archivo (excepto el uso de variables globales).

Aquí es la parte relevante de la secuencia de comandos, donde he tratado de pasar el parámetro:

use File::Find; 

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

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

$isDryRun es un escalar. $startDir es una cadena, ruta completa a un directorio.

$IsDryRun2 no está configurado:

El uso de inicializar valor $ IsDryRun2 en la concatenación o cuerda en línea TIFFconvert.pl 197 (# 1) (W sin inicializar) un valor indefinido se utilizó como (.) si ya se definió . Fue interpretado como "" o "0", pero tal vez fue un error. Para suprimir esta advertencia, asigne un valor definido a sus variables.

(La vieja llamada sin parámetros fue: find (\&findFiles, $startDir);)


plataforma de prueba (pero la casa de producción será una máquina Linux, Ubuntu 9.1, Perl 5.10, 64 bits): ActiveState Perl 64 bits . Windows XP. Desde perl -v: v5.10.0 creado para MSWin32-x64-multi-thread Binary build 1004 [287188] proporcionado por ActiveState.

Respuesta

15

Es necesario crear una referencia de sub que llama a su sub deseada con los parámetros deseados:

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

Esto es, más o menos, currificación. Simplemente no es bonito currying. :)

+0

Gracias, funcionó. ¿Se requiere el primer punto y coma (tercera línea)? –

+0

No necesita ese punto y coma, pero no está de más tenerlo allí. –

+0

@hobbs => siempre me ha gustado la forma en que Perl maneja el currificado con subs anónimos. ¿Qué sería lindo para ti? –

3

Puede crear cualquier tipo de referencia de código que desee. No tiene que usar una referencia a una subrutina con nombre. Para ver muchos ejemplos de cómo hacerlo, consulte mi módulo File::Find::Closures. Creé ese módulo para responder precisamente a esta pregunta.

0
# 
# ----------------------------------------------------------------------------- 
# Read directory recursively and return only the files matching the regex 
# for the file extension. Example: Get all the .pl or .pm files: 
#  my $arrRefTxtFiles = $objFH->doReadDirGetFilesByExtension ($dir, 'pl|pm') 
# ----------------------------------------------------------------------------- 
sub doReadDirGetFilesByExtension { 
    my $self = shift; # Remove this if you are not calling OO style 
    my $dir = shift; 
    my $ext = shift; 

    my @arr_files =(); 
    # File::find accepts ONLY single function call, without params, hence: 
    find(wrapp_wanted_call(\&filter_file_with_ext, $ext, \@arr_files), $dir); 
    return \@arr_files; 
} 

# 
# ----------------------------------------------------------------------------- 
# Return only the file with the passed extensions 
# ----------------------------------------------------------------------------- 
sub filter_file_with_ext { 
    my $ext  = shift; 
    my $arr_ref_files = shift; 

    my $F = $File::Find::name; 

    # Fill into the array behind the array reference any file matching 
    # the ext regex. 
    push @$arr_ref_files, $F if (-f $F and $F =~ /^.*\.$ext$/); 
} 

# 
# ----------------------------------------------------------------------------- 
# The wrapper around the wanted function 
# ----------------------------------------------------------------------------- 
sub wrapp_wanted_call { 
    my ($function, $param1, $param2) = @_; 

    sub { 
     $function->($param1, $param2); 
    } 
} 
+0

Es posible que desee agregar una explicación para el código de muestra. Y tal vez muestrear el uso de las 3 funciones. –

+0

En mi humilde opinión los comentarios de func son suficientes + el uso se muestra para el funcion doReadDirGetFilesByExtension.Realmente creo que si un usuario no obtiene lo que esos funcs hacen con estos comentarios y descripciones que probablemente él/ella no debería usar este código ya que podría perder más tiempo ajustándolo a sus necesidades en comparación con encontrar una solución para su problema de otra manera - TMTOWTDI ... –

Cuestiones relacionadas