2010-09-25 8 views
18

Ich bin ein wenig verwirrt von File::Find Dokumentation ... Was ist das Äquivalent zu $ find my_dir -maxdepth 2 -name "*.txt"?Wie kann ich File :: Find in Perl verwenden?

+0

'mein @files = \' finden my_dir $ -maxdepth 2 -name * .txt \ ';' ... Ich habe nicht die 'Wanted' sub bekommen. Kann ich nicht einfach eine Regex geben? –

+0

Eine andere Frage zu [Dateien mit Perl finden] (http://stackoverflow.com/questions/17754931/finding-files-with-perl) erwähnt einige Alternativen, die in den Antworten unten nicht erwähnt werden. –

Antwort

31

Persönlich bevorzuge ich File::Find::Rule, da Sie keine Callback-Routinen erstellen müssen.

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); 

Oder alternativ einen Iterator erstellen:

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

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

+1 Ich denke, das ist die einfachste, die meisten '$ find'-ähnliche Lösung vorgeschlagen. –

+0

leider mit Iterator, holt es alle Verzeichnisstruktur in den Speicher. Wenn die Struktur so groß (typisch) ist, wird der Prozess viel Speicher verbrauchen. Deshalb ist diese Entschließung oft nicht gut. Im Gegensatz dazu bietet scannind dir tree by system find-Befehl eine Option zum Online-Abruf, ohne viel RAM zu verbrauchen. – Znik

7

Ich glaube, ich nur ein glob verwenden würde, da Sie wirklich alle Sachen, die Directory-Traversal nicht brauchen:

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

ich File::Find::Closures gemacht, um es einfach für Sie, die Rückrufe zu erstellen, die Sie weitergeben zu 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->(); 

Normalerweise können Sie eine Such drehen (1) Befehl in ein Perl-Programm mit find2perl (in V5.20 entfernt, aber auf CPAN):

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

Aber anscheinend find2perl versteht nicht -maxdepth, so dass Sie, dass weg verlassen können:

% 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"); 
} 

Nun, da Sie die Start Programmierung haben, können Sie in stecken, was auch immer, was Sie brauchen, einschließlich einem preprocess Schritt beschneide den Baum.

+0

+1 Danke! gut zu finden über '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

Danke - das ist genau das, was ich gesucht habe. – Winter

2

Es gibt auch das handliche find2perl Dienstprogramm. Verwenden Sie es anstelle des Befehls Unix find mit den gleichen Befehlszeilenargumenten wie 'find' und es wird der entsprechende Perl-Code generiert, der File :: Find verwendet.

$ find2perl my_dir -maxdepth 2 -name "*.txt" 
Verwandte Themen