我如何以递归方式读出Perl中的目录?

Prz*_*mek 11 directory treeview recursion perl

我想以递归方式读出一个目录,以便在带有Template :: Toolkit的HTML-Page中打印数据结构.但我在如何以一种可以轻松阅读的形式保存路径和文件.

我的想法是这样开始的

sub list_dirs{

     my ($rootPath) = @_;
     my (@paths);

     $rootPath .= '/' if($rootPath !~ /\/$/);

     for my $eachFile (glob($path.'*'))
     {

         if(-d $eachFile)
         {
              push (@paths, $eachFile);

              &list_dirs($eachFile);
          }
          else
          {
              push (@files, $eachFile);
          }
     }

 return @paths;
}
Run Code Online (Sandbox Code Playgroud)

我怎么能解决这个问题?

Htb*_*baa 19

这应该可以解决问题

 use strict;
 use warnings;
 use File::Find qw(finddepth);
 my @files;
 finddepth(sub {
      return if($_ eq '.' || $_ eq '..');
      push @files, $File::Find::name;
 }, '/my/dir/to/search');
Run Code Online (Sandbox Code Playgroud)


小智 8

您应始终使用严格和警告来帮助您调试代码.例如,Perl会警告你@files没有声明.但是你的函数的真正问题是你@paths在每次递归调用时声明一个词法变量,list_dirs并且在递归步骤之后不要将返回值推回.

push @paths, list_dir($eachFile)
Run Code Online (Sandbox Code Playgroud)

如果您不想安装其他模块,以下解决方案可能对您有所帮助:

use strict;
use warnings;
use File::Find qw(find);

sub list_dirs {
        my @dirs = @_;
        my @files;
        find({ wanted => sub { push @files, $_ } , no_chdir => 1 }, @dirs);
        return @files;
}
Run Code Online (Sandbox Code Playgroud)


FMc*_*FMc 5

mdom的答案解释了你最初的尝试是如何误入歧途的.我还建议你考虑更友好的替代方案File::Find.CPAN有几种选择.这是一个.

use strict;
use warnings;
use File::Find::Rule;
my @paths = File::Find::Rule->in(@ARGV);
Run Code Online (Sandbox Code Playgroud)

另见:

这是重写您的递归解决方案.注意事项:use strict; use warnings; 并使用范围块为子例程创建静态变量.

use strict;
use warnings;

print $_, "\n" for dir_listing(@ARGV);

{
    my @paths;
    sub dir_listing {
        my ($root) = @_;
        $root .= '/' unless $root =~ /\/$/;
        for my $f (glob "$root*"){
            push @paths, $f;
            dir_listing($f) if -d $f;
        }
        return @paths;
    }
}
Run Code Online (Sandbox Code Playgroud)