以特定条件递归查找具有特定名称的所有路径

时间:2018-12-06 12:21:15

标签: perl

我试图递归地在specif目录中找到所有名为test.json的文件,并将它们插入数组。 它们始终位于json_files_<id_num>中的<id_num>log_dir =唯一ID号)目录中。但是log_dir也可以包含也有此文件的full_json_files目录。 我正在尝试创建一个实用程序,该实用程序将遍历输入目录中的所有路径并查找到test.json文件的所有路径。 但是,如果我们在full_json_files目录中有log_dir目录,那么我想使用full_json_files/test.json而不是json_files<id_num>

我将通过一个例子来使之更有意义。请考虑以下层次结构:

- somePath1
    - log_dir
        - json_files_12345
            - test.json
- somePath2
    - log_dir
        - json_files_543
            - test.json 
        - full_json_files
            - test.json
- somePath3
    - log_dir
        - json_files_123

预期输出:

somePath1/log_dir/json_files_12345/test.json
somePath2/log_dir/full_json_files/test.json

请注意,somePath1,somePath2,somePath3是从输入目录($main_dir)开始的所有路径。 我虽然使用了File::Find模块,所以我做了一些基本的事情:

find( 
    sub { push (@dirs,$File::Find::name) if(basename($File::Find::name) eq "test.json"); }, 
    $main_dir
);

它将把@dirs文件的所有路径插入test.json。但是我想以某种方式在sub中组合以上条件。 另外,我想声明该子例程分开并按引用传递(使用&),并在该子例程中进行所有检查。 我该怎么办? File::find是解决此问题的好方法吗?如果没有,那还有什么其他方法呢?

这应该是非常基本的,但是由于某些原因,我很难从这一点继续。

2 个答案:

答案 0 :(得分:1)

这是一种使用@files后处理和临时哈希%full_json_dir来记录目录是否包含“完整”文件的方法:

use feature qw(say);
use strict;
use warnings;

use File::Basename qw(basename dirname);
use File::Find;

my @files;
my $main_dir = '.';
my %full_json_dir;

find( sub { wanted( \@files, $_ ) }, $main_dir);

sub wanted {
    my ( $files, $name ) = @_;

    if ( $name eq 'test.json' ) {
        push @$files, $File::Find::name;
        my $pdir = dirname $File::Find::dir;
        my $full_dir = ( (basename $File::Find::dir) eq "full_json_files" ) ? 1 : 0;
        if ( exists $full_json_dir{$pdir} ) {
            if ( !$full_json_dir{$pdir} ) {
                $full_json_dir{$pdir} = $full_dir;
            }
        }
        else {
            $full_json_dir{$pdir} = $full_dir;
        }
    }
} 

my @files2;
for my $file (@files) {
    my $dir = dirname $file;
    my $pdir = dirname $dir;
    if ( $full_json_dir{$pdir} == 1) {
        push @files2, $file;
        $full_json_dir{$pdir} = 2;
    }
    elsif ( $full_json_dir{$pdir} == 0 )  {
        push @files2, $file;
    }
}


say for @files2;

输出

./somePath1/log_dir/json_files_12345/test.json
./somePath2/log_dir/full_json_files/test.json

答案 1 :(得分:0)

IO::All的必需插头:

perl -MIO::All -E 'say for io("./mydir")->filter(sub{ /test.json/ })->All_Files'

或者,作为脚本而不是单行代码:

use IO::All;
my @testfiles = io->dir("./mydir")->filter(sub{ /test.json/ })->All_Files;
print join "\n", @testfiles ;

对不起:-)