首次匹配后如何中止File :: Find :: Rule?

时间:2018-01-27 08:01:42

标签: perl

我正在使用 File::Find::Rule 在下面的代码片段中递归搜索 给定目录中的文件。

Perl代码

my $WD = Cwd::abs_path();

my @files = File::Find::Rule->file()->relative()->name( '*.txt' )->in($WD);

for my $file ( @files ) {
    print "file: $file\n";
}

目录结构

|--- DIR1
     |-- subdir1
             |-- *.txt
     |-- subdir2
             |-- *.txt
             |-- *.txt

当前输出

DIR1/subdir1/*.txt
DIR1/subdir2/*.txt
DIR1/subdir2/*.txt

期望的输出

DIR1/subdir1/*.txt

有人可以建议可以做些什么吗?

1 个答案:

答案 0 :(得分:2)

一种方法是使用its exec,以便在找到的文件路径发生变化后停止匹配

my @files = File::Find::Rule->file->relative->name('*.txt')
    ->exec( sub { 
        state $path = ''; 
        return 0 if $path and $path ne $_[1]; 
        $path = $_[1]; 
     }
)->in($WD); 

找到文件后调用exec中的子例程,其中文件路径作为@_中的第二个参数。一旦该路径从此处改变到该点,则意味着搜索已在不同目录中找到文件。

一旦发生这种情况,我们就会停止更改$path,以便该目录上的所有进一步查询都失败。

这是检测找到文件的目录更改的简单方法。例如,使用return 0替换say "Changed from $path to $_[1]";进行检查。

经过测试perl -Mstrict -MFile::Find::Rule -wE'...',代码中的'"

注意:state需要use feature 'state';(除非您在use v5.10或更高版本之下)。在单行中,-E(而不是-e)在主编译单元中启用所有feature

早期的评论改变(或模糊)标题中的要求在所述条件下完全中止。在这种情况下die而不是return 0,在eval

my @files;
eval { 
    @files = File::Find::Rule->file->relative->name('*>txt')
        ->exec( sub { 
            state $path = ''; 
            die "CHANGED_DIR\n" if $path and $path ne $_[1];
            $path = $_[1];
        })
        ->in($WD);
} or do { die $@ if $@ ne 'CHANGED_DIR' }

其中die的字符串仅用于我们可以检查并在需要时重新抛出。