递归Perl的细节需要帮助(Recursive Perl detail need help)

2019-11-04 09:50发布

我认为这是一个简单的问题,但我坚持了下来一段时间了! 我需要一双崭新的眼睛这一点。

事情是我有这样的代码在Perl:

#!c:/Perl/bin/perl
use CGI qw/param/;  
use URI::Escape; 

print "Content-type: text/html\n\n";

my $directory = param ('directory'); 
$directory = uri_unescape ($directory); 

my @contents;
readDir($directory);


foreach (@contents) {
  print "$_\n";
}

#------------------------------------------------------------------------
sub readDir(){
 my $dir = shift;
    opendir(DIR, $dir) or die $!;
    while (my $file = readdir(DIR)) {
  next if ($file =~ m/^\./);
  if(-d $dir.$file)
  {
   #print $dir.$file. " ----- DIR\n";
   readDir($dir.$file);
  }
  push @contents, ($dir . $file);
    }
    closedir(DIR);
}

我试图让它递归。 我需要所有的目录和子目录中的所有文件,完整路径,这样我可以在以后打开文件。

但我只输出返回它找到的第一个目录在当前目录中的文件和文件。 如果我有目录内的3个文件夹只显示第一个。

防爆。 CMD通话:

"perl readDir.pl directory=C:/PerlTest/"

谢谢

Answer 1:

有许多模块可用于目录中的递归列表文件。

我最喜欢的是文件::查找::规则

    use strict ;
    use Data::Dumper ;
    use File::Find::Rule ;
    my $dir = shift ;   # get directory from command line

    my @files = File::Find::Rule->in( $dir );
    print Dumper( \@files ) ;

它发送的文件列表到一个数组(你的程序在做什么)。

$VAR1 = [
      'testdir',
      'testdir/file1.txt',
      'testdir/file2.txt',
      'testdir/subdir',
      'testdir/subdir/file3.txt'
    ];

有一个负载的其他选项,如仅列出特别名称的文件。 或者你可以将其设置为一个迭代器,这是在描述如何使用文件::查找

如何使用文件::查找在Perl?

如果你要坚持来与Perl的核心单元,看看文件::查找。



Answer 2:

避免轮再造,使用CPAN。

use Path::Class::Iterator;
my $it = Path::Class::Iterator->new(
        root => $dir,
        breadth_first => 0
);
until ($it->done) {
        my $f = $it->next;
        push @contents, $f;
}

请确保你不要让人家设置$dir的东西,可以让他们看看什么地方你不希望他们看。



Answer 3:

你的问题是目录范围处理DIRDIR具有全局范围所以每次递归调用readDir使用相同的DIR ; 所以,当你closdir(DIR)并返回给调用者,调用者做了readdir在一个封闭的目录句柄,一切都停止。 解决的办法是使用本地目录句柄:

sub readDir {
    my ($dir) = @_;
    opendir(my $dh, $dir) or die $!;
    while(my $file = readdir($dh)) {
        next if($file eq '.' || $file eq '..');
        my $path = $dir . '/' . $file;
        if(-d $path) {
            readDir($path);
        }
        push(@contents, $path);
    }
    closedir($dh);
}

还要注意的是,你会错过一个目录分隔如果(a)它是不是在年底$directory或(b)在每次递归调用。 据我所知,斜线将在内部转换为在Windows反斜杠,但你可能想使用压延从CPAN模块的路径反正(我只在乎Unix系统,所以我没有任何建议)。

我也建议你传递给一个参考@contentsreadDir ,而不是把它当作一个全局变量,减少错误和减少混乱的方式。 而且不要使用括号sub ,除非你知道他们做什么,他们在做什么的定义。 一些健全检查和清理在$directory将是一个不错的主意为好。



文章来源: Recursive Perl detail need help