2010-09-25 36 views
18

Tôi hơi bối rối từ tài liệu File::Find ... Tương đương với số $ find my_dir -maxdepth 2 -name "*.txt" là gì?Làm cách nào để sử dụng Tệp :: Tìm trong Perl?

+0

'my @files = \' tìm $ my_dir -maxdepth 2 -name * .txt \ ';' ... Tôi không nhận được phần phụ 'Wanted'. Tôi không thể chỉ cho một regex? –

+0

Một câu hỏi khác về [Tìm tệp bằng Perl] (http://stackoverflow.com/questions/17754931/finding-files-with-perl) đề cập đến một số lựa chọn thay thế không được đề cập trong các câu trả lời bên dưới. –

Trả lời

31

Cá nhân, tôi thích File::Find::Rule vì điều này không cần bạn tạo thói quen gọi lại.

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

Hoặc cách khác tạo ra một iterator:

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

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

+1 Tôi nghĩ đây là giải pháp đơn giản nhất,' $ find' giống như được đề xuất. –

+0

không may với trình vòng lặp, nó lấy tất cả cấu trúc thư mục vào bộ nhớ. khi cấu trúc quá lớn (điển hình), thì quá trình sẽ tiêu tốn rất nhiều bộ nhớ. Đó là lý do tại sao độ phân giải này thường không tốt. Ngược lại, cây dir scannind bằng lệnh tìm hệ thống cung cấp tùy chọn tìm nạp trực tuyến mà không tốn nhiều RAM. – Znik

7

Tôi nghĩ rằng tôi chỉ muốn sử dụng một glob kể từ khi bạn thực sự không cần tất cả những thứ thư mục traversal:

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

tôi đã File::Find::Closures để làm cho nó dễ dàng cho bạn để tạo ra các callbacks mà bạn vượt qua 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->(); 

Thông thường, bạn có thể biến một find (1) lệnh vào một chương trình Perl với find2perl (loại bỏ trong v5.20 nhưng trên CPAN):

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

Nhưng dường như find2perl không hiểu -maxdepth, vì vậy bạn có thể rời khỏi rằng off:

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

Bây giờ bạn đã các lập trình bắt đầu, bạn có thể cắm vào bất cứ điều gì khác mà bạn cần, bao gồm một bước preprocess để tỉa cây.

+0

+1 Cảm ơn! tốt để tìm hiểu về '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

Cảm ơn - đây chỉ là những gì tôi đang tìm kiếm. – Winter

2

Ngoài ra còn có các tiện ích find2perl. Sử dụng nó thay vì lệnh Unix find, với các đối số dòng lệnh giống như 'find', và nó sẽ tạo ra mã Perl tương ứng sử dụng File :: Find.

$ find2perl my_dir -maxdepth 2 -name "*.txt" 
Các vấn đề liên quan