Perl中的递归目录遍历

时间:2012-02-27 19:23:22

标签: perl recursion

我正在尝试编写一个脚本,从脚本所在的文件夹开始打印出文件结构。脚本工作正常,没有递归调用但是通过该调用它会打印第一个文件夹的内容并崩溃以下消息:closedir()尝试在printFiles.pl第24行无效的dirhandle DIR。文件夹被打印,执行到达最后一行,但为什么不进行递归调用?我应该如何解决这个问题呢?

 #!/usr/bin/perl -w

printDir(".");
sub printDir{
opendir(DIR, $_[0]);
local(@files);
local(@dirs);
 (@files) = readdir(DIR);
 foreach $file (@files) {
    if (-f $file) {
      print $file . "\n";
    }
    if (-d $file && $file ne "." && $file ne "..") {
      push(@dirs, $file);
    }
 } 
 foreach $dir (@dirs) {
   print "\n";
   print $dir . "\n";
   printDir($dir);
 }
 closedir(DIR);
}

3 个答案:

答案 0 :(得分:7)

  • 在Perl程序开始时,您应始终use strict;use warnings;,尤其是在您寻求帮助之前。这样Perl就会出现很多直截了当的错误,否则你可能不会注意到。

  • 无效文件句柄错误可能是因为DIR是一个全局目录句柄,并且已经由先前执行的子例程关闭了。最好始终对文件和目录使用词法句柄,并测试返回代码以确保打开成功,如下所示

    opendir my $dh, $_[0] or die "Failed to open $_[0]: $!";
    

    词法文件句柄的一个优点是当它们超出范围时会隐式关闭它们,因此在子例程结束时不需要进行closedir调用。

  • local并不意味着像这样使用。它不足以作为声明,并且您正在创建一切可以访问的全局变量的临时副本。最好使用my,就像这样

    my @dirs;
    my @files = readdir $dh;
    
  • 此外,您在readdir中使用的文件名没有路径,因此除非您对正在处理的目录chdir或附加目录路径字符串,否则您的文件测试将失败测试前的文件名。

答案 1 :(得分:3)

使用File::Find模块。我通常这样做的方法是使用perl附带的find2perl工具,它使用与 find 相同的参数,并使用File :: Find创建一个合适的perl脚本。然后我微调生成的脚本来做我想要它做的事情。但也可以直接使用File :: Find。

答案 2 :(得分:3)

为什么不use File::Find

use strict; #ALWAYS!
use warnings; #ALWAYS!
use File::Find;

find(sub{print "$_\n";},".");