【问题标题】:How can I use File::Find in Perl?如何在 Perl 中使用 File::Find?
【发布时间】:2010-09-25 20:38:07
【问题描述】:

我对@9​​87654322@ 文档感到有些困惑...$ find my_dir -maxdepth 2 -name "*.txt" 的等价物是什么?

【问题讨论】:

  • my @files = `find $my_dir -maxdepth 2 -name *.txt`;... 我没有得到Wanted 子。我不能只给出一个正则表达式吗?
  • 关于Finding files with Perl 的另一个问题提到了以下答案中未提及的一些替代方案。

标签: perl find


【解决方案1】:

就个人而言,我更喜欢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"
}

【讨论】:

  • +1 我认为这是最简单、最推荐 $ find 的解决方案。
  • 不幸的是,它使用迭代器将所有目录结构提取到内存中。当结构如此大(典型)时,进程将消耗大量内存。这就是为什么这个分辨率通常不好。相反,通过系统查找命令扫描目录树提供了在不消耗大量 RAM 的情况下在线获取它的选项。
【解决方案2】:

我想我会使用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->();

通常,您可以使用 find2perl 将 find(1) 命令转换为 Perl 程序(在 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+"$@"}'
        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 步骤。

【讨论】:

    【解决方案3】:
    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" ;   
    } 
    

    【讨论】:

    • 谢谢 - 这正是我想要的。
    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-11
      • 2013-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多