2010-09-25 92 views
18

我从File::Find文档有点困惑...什么是$ find my_dir -maxdepth 2 -name "*.txt"的等效什么?如何在Perl中使用File :: Find?

+0

'my @files = \'find $ my_dir -maxdepth 2 -name * .txt \';'...我没有得到'Wanted'子。我不能给一个正则表达式吗? – 2010-09-25 21:07:58

+0

关于[用Perl查找文件]的另一个问题(http://stackoverflow.com/questions/17754931/finding-files-with-perl)提到了下面答案中没有提到的一些替代方法。 – 2015-01-05 15:00:35

回答

31

个人而言,我更喜欢File::Find::Rule,因为这不需要您创建回调例程。

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

或可替换地创建一个迭代器:

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

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

+1我认为这是最简单的,最类似'$ find'的解决方案。 – 2010-09-28 15:17:48

+0

不幸的是与迭代器,它将所有目录结构提取到内存中。当结构如此之大(典型)时,进程将消耗大量内存。它为什么这个决议往往不好。相反,通过系统查找命令的scannind dir树给出了在不消耗大量RAM的情况下在线获取它的选项。 – Znik 2018-02-02 13:46:09

7

我想我只是用一个glob因为你真的不需要所有的目录遍历东西:

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

我做了File::Find::Closures,使您可以轻松创建您传递给回调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->(); 

通常情况下,你可以把一个发现(1)命令进入Perl程序与find2perl(在V5.20但CPAN删除):

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

但显然find2perl不明白-maxdepth,所以你可以离开这个关:

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

现在你已经开始编程,你可以在你需要的任何东西,包括preprocess一步堵塞修剪树。

+0

+1谢谢!很好找到关于'File :: Find :: Closures'的问题 – 2010-09-28 15:17:18

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

谢谢 - 这正是我正在寻找的。 – Winter 2011-12-28 20:43:42

2

另外还有方便实用find2perl。使用它而不是Unix find命令,使用与find相同的命令行参数,它将生成相应的使用File :: Find的Perl代码。

$ find2perl my_dir -maxdepth 2 -name "*.txt" 
相关问题