2010-09-25 27 views
18

Estoy un poco confundido de la documentación File::Find ... ¿Cuál es el equivalente a $ find my_dir -maxdepth 2 -name "*.txt"?¿Cómo puedo usar File :: Find in Perl?

+0

'mis @files = \' find $ mi_dir -maxdepth 2 -name * .txt \ '; '... No entiendo la' sub Wanted'. ¿No puedo dar una expresión regular? –

+0

Otra pregunta sobre [Buscar archivos con Perl] (http://stackoverflow.com/questions/17754931/finding-files-with-perl) menciona algunas alternativas que no se mencionan en las respuestas a continuación. –

Respuesta

31

Personalmente, prefiero File::Find::Rule ya que no es necesario que cree rutinas de devolución de llamada.

use strict; 
use Data::Dumper; 
use File::Find::Rule; 

my $dir = shift; 
my $level = shift // 2; 

my @files = File::Find::Rule->file() 
          ->name("*.txt") 
          ->maxdepth($level) 
          ->in($dir); 

print Dumper(\@files); 

O, alternativamente, crear un iterador:

my $ffr_obj = File::Find::Rule->file() 
           ->name("*.txt") 
           ->maxdepth($level) 
           ->start($dir); 

while (my $file = $ffr_obj->match()) 
{ 
    print "$file\n" 
} 
+0

+1 Creo que esta es la solución más simple, más' $ find' -like sugerida. –

+0

desafortunadamente con el iterador, recupera toda la estructura del directorio en la memoria. cuando la estructura es tan grande (típica), el proceso consumirá mucha memoria. Es por eso que esta resolución a menudo no es buena. En sentido opuesto, Scannind dir tree por el comando system find da la opción de ir a buscarlo en línea sin consumir gran cantidad de RAM. – Znik

7

Creo que sólo haría uso de un glob ya que realmente no necesita todas las cosas recorrido de directorios:

my @files = glob('*.txt */*.txt'); 

hice File::Find::Closures para hacer más fácil para usted para crear las devoluciones de llamada que se pasan a find:

use File::Find::Closures qw(find_by_regex); 
use File::Find qw(find); 

my($wanted, $reporter) = File::Find::Closures::find_by_regex(qr/\.txt\z/); 

find($wanted, @dirs); 

my @files = $reporter->(); 

Normalmente, puede activar un (1) comando find en un programa de Perl con find2perl (eliminado en v5.20 pero en CPAN):

% find2perl my_dir -d 2 -name "*.txt" 

Pero al parecer no entiende find2perl-maxdepth, por lo que podría dejar que fuera:

% find2perl my_dir -name "*.txt" 
#! /usr/local/perls/perl-5.13.5/bin/perl5.13.5 -w 
    eval 'exec /usr/local/perls/perl-5.13.5/bin/perl5.13.5 -S $0 ${1+"[email protected]"}' 
     if 0; #$running_under_some_shell 

use strict; 
use File::Find(); 

# Set the variable $File::Find::dont_use_nlink if you're using AFS, 
# since AFS cheats. 

# for the convenience of &wanted calls, including -eval statements: 
use vars qw/*name *dir *prune/; 
*name = *File::Find::name; 
*dir = *File::Find::dir; 
*prune = *File::Find::prune; 

sub wanted; 



# Traverse desired filesystems 
File::Find::find({wanted => \&wanted}, 'my_dir'); 
exit; 


sub wanted { 
    /^.*\.txt\z/s 
    && print("$name\n"); 
} 

Ahora que ha de comenzar la programación, se puede conectar en cualquier otra cosa que necesita, incluyendo un paso a preprocess podar el árbol

+0

+1 ¡Gracias! bueno para encontrar sobre 'File :: Find :: Closures' –

6
use File::Find ; 
use Cwd ; 

my $currentWorkingDir = getcwd; 

my @filesToRun =(); 
my $filePattern = '*.cmd' ; 
#add only files of type filePattern recursively from the $currentWorkingDir 
find(sub { push @filesToRun, $File::Find::name 
            if (m/^(.*)$filePattern$/) }, $currentWorkingDir) ; 

foreach my $file (@filesToRun ) 
{ 
    print "$file\n" ; 
} 
+0

Gracias - esto es justo lo que estaba buscando. – Winter

2

También existe la práctica find2perl utilidad. Úselo en lugar del comando de búsqueda de Unix, con los mismos argumentos de línea de comandos que 'encontrar', y generará el código de Perl correspondiente que hace uso de File :: Find.

$ find2perl my_dir -maxdepth 2 -name "*.txt" 
Cuestiones relacionadas