2008-12-19 4 views
5

Estoy usando el módulo File::Find para recorrer un árbol de directorios. Una vez que encuentre un archivo específico, quiero dejar de buscar. ¿Cómo puedo hacer eso?¿Cómo puedo salir de la función de búsqueda recursiva una vez que se encuentra un archivo específico?

find (\$processFile, $mydir); 

    sub processFile() { 
     if ($_ =~ /target/) { 
     # How can I return from find here? 
     } 
    } 
+0

¿Se refiere al módulo "Archivo :: Buscar", en lugar de "Archivo :: Encontrado"? – BrianH

+0

Sí, gracias. Edité la pregunta. – MCS

Respuesta

9

Parece que va a tener que morir:

eval { 
    find (\$processFile, $mydir); 
}; 

if ([email protected]) { 
    if ([email protected] =~ m/^found it/) { 
     # be happy 
    } 
    else ([email protected]) { 
     die [email protected]; 
    } 
} 
else { 
    # be sad 
} 


sub processFile() { 
    if ($_ =~ /target/) { 
     die 'found it'; 
    } 
} 
+0

Esto parece funcionar. Soy bastante nuevo para Perl: ¿este es un uso típico de eval? – MCS

+1

Muy. Ver 'perldoc -f eval'. –

+0

Es básicamente una excepción sin una clase. Si desea tener más control y asegurarse de que no se trata de otro error que coincida con "lo encontró", puede utilizar algo como Exception :: Class. – mpeters

1

¿Puedes lanzar excepciones personalizadas en Perl?

+0

Creo que hay un módulo para esto, pero es un truco. – Keltia

+0

Simplemente pase un objeto para morir() en lugar de una cadena. –

-4

El processFile función() debe devolver verdadero si encuentra el archivo, y falso en caso contrario. Por lo tanto, cada vez que processFile se llame a sí mismo debería verificar este valor de retorno. Si es cierto, alguna llamada recursiva ha encontrado el archivo, por lo que no es necesario volver a llamarse a sí mismo, y también debe volverse verdadero. Si es falso, el archivo aún no se ha encontrado y debería continuar la búsqueda.

+0

Así no es como funciona File :: Find. –

+0

Puede que no sea correcto para File :: Find, pero es una forma correcta para una función de búsqueda recursiva enrollada a mano (todas las funciones recursivas deben tener una forma de terminar, y esta es una forma aceptable de hacerlo). –

-1

He encontrado este enlace:

http://www.perlmonks.org/index.pl?node_id=171367

he copiado una de las secuencias de comandos en esa lista de mensajes, y esto parece que funciona:

#! /usr/bin/perl -w 

use strict; 
use File::Find; 

my @hits =(); 
my $hit_lim = shift || 20; 

find(
    sub { 
     if(scalar @hits >= $hit_lim) { 
      $File::Find::prune = 1; 
      return; 
     } 
     elsif(-d $_) { 
      return; 
     } 
     push @hits, $File::Find::name; 
    }, 
    shift || '.' 
); 

$, = "\n"; 
print @hits, "\n"; 

Parece que hallazgo que realmente está causando para no atravesar más usando $ File :: Find :: prune.

+0

Intenté configurar $ File :: Find :: prune y no funcionó.Parece que la configuración de prune en un directorio detendrá la búsqueda al descender en ese directorio, pero no impedirá que continúe procesando otros directorios (o archivos). – MCS

+0

Bien - Cuando ejecuto ese script arriba, corta en 20 resultados y por lo que puedo decir, también detiene la función de búsqueda. (agregar el "retorno" podría evitar que los resultados se agreguen a la matriz, pero estoy bastante seguro de que File :: Find realmente se está deteniendo). Lo siento, no está funcionando para ti ... – BrianH

0

Puede usar bloques con nombre y saltar a él si encuentra su resultado (con el siguiente, último, depende de lo que necesite).

3

Además de lo que dijeron todos los demás, es posible que desee echar un vistazo a File-Find-Object, que es a la vez iterativo (y como tal puede interrumpirse en el medio) y capaz de creación de instancias (para iniciar y usar varios de inmediato, o crea una instancia de un objeto FFO mientras se realiza otro escaneo, etc.)

Lo malo es que no es núcleo, pero solo tiene Class :: Accessor como dependencia, y es puro-Perl por lo tanto, no debería ser difícil de instalar.

Debo advertirle que soy su mantenedor, por lo que podría ser un poco parcial.

Cuestiones relacionadas