【问题标题】:In Perl how to use recursion to search directories and sub directories and specify the depth?在 Perl 中如何使用递归搜索目录和子目录并指定深度?
【发布时间】:2014-04-03 10:29:32
【问题描述】:

所以我知道你可以在子程序中,使用 opendir 打开目录,然后使用 readdir 读取当前工作目录中的所有文件,然后将所有文件推送到一个数组中。如果它是一个文件,则遍历该数组,然后打印该文件或将该文件推送到一个新数组中,否则如果它是一个目录,则再次递归调用子例程。我不明白的是我会在哪里指定深度。任何帮助是极大的赞赏。


以下是我在您的帮助下得出的解决方案:

 read_dir('test', 1);

 sub read_dir {
    $dir = shift;
    $level = shift;

    chdir ($dir);
    opendir(DIR, '.') or die "Can't open $dir: $!";
    @filesarray = readdir (DIR) or die;
    closedir(DIR);
    my @files;
    foreach my $file (@filesarray) {
        if (-f $file && $file =~ /\.txt$/i){
              push @files, $file;
            } ## end of if

        elsif (-d $file) {
              next if ($file eq ".");
              next if ($file eq "..");
              $dir = $file;
              read_dir($dir, $level+1); ## QUESTION IS HERE?????
         } ## end of elsif
    } ## end of foreach

    foreach my $file1 (@files) {
         print "$file1\n";
    }
} ## end of sub read_dir

【问题讨论】:

标签: perl recursion directory subdirectory depth


【解决方案1】:

您可以将参数传递给称为level 的递归函数,并将该函数称为recurse(level+1, subdirectory)

无论如何,最好使用像 File::Find 这样的专用库来完成这项任务。

【讨论】:

  • 你能看一下上面的代码吗?我仍然很困惑在哪里执行深度我将条件放在哪里。再次感谢您的帮助。
  • 任何你想去的地方,但可能在read_dir 的开头附近。 (return if $level > 5;)
【解决方案2】:

不过,这是很好的锻炼,可以驱散懒惰......

<pre><code>

#!/usr/bin/perl
use DirFind;
my $max = shift(@ARGV);
my $dir = shift(@ARGV);
my $filter = shift(@ARGV);
my %args = (
    maxdepth => $max,
    dirs => $dir,
    filter => $filter
);
# recursive
my $df_r = DirFind->new(%args);
print join("\n", $df_r->reader_r()->result_files()),"\n\n";
exit;

package DirFind;

#
# essentially mimic find
#

#
# we'll be storing things away so we want an object
#
sub new {
    my ($class, @rest) = @_;
    my $self = bless({@rest}, $class);
    # for the sake of all things being equal manufacture the level
    # and translate to listref context so that the new() args can
    # be just the simpler dirs => path
    my $dir = $self->{dirs};
    $self->{dirs}->[0] = join(' ', $dir, 0);
    return $self;
}

#
# with tail recursion we need to store the filter and depth in new()
#
sub reader_r {
    my ($self) = @_;
    my ($d, $lvl) = split(' ', shift(@{$self->{dirs}}));
    # no more directories
    return if (!defined($d) || !defined($lvl));
    return if ($lvl == $self->{maxdepth});
    $lvl++;
    # making the regex a bit more protected
    my $filter = $self->{filter};
    opendir(my $dh, $d);
    my @basefiles = readdir($dh);
    closedir($dh);
    foreach my $f (@basefiles) {
        next if ($f =~ /^\.{1,2}$/);
        my $file = join('/', $d, $f);
        # implicitly skip symlinks
        push(@{$self->{dirs}}, join(' ', $file, $lvl)) if (-d $file);
        if (-f $file) {
        if (defined($filter)) {
            next unless ($file =~ m!$filter!);
            push(@{$self->{files}}, $file);
        }
        }
    }
    if (@{$self->{dirs}}) {
        $self->reader_r();
    }
    # for chaining
    return $self;
}

#
# the recursive form requires the additional call to get the results
# no we chain them
#
sub result_files {
    my ($self) = @_;
    return wantarray? @{$self->{files}}: $self->{files};
}
1;
</code></pre>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 2021-05-25
    • 2010-12-01
    相关资源
    最近更新 更多