5

我正在编写一个程序来逐步遍历目录树(是的,我知道 File::Find,但我正在编写一个替代品)。

在我的程序中,我正在readdir对整个目录进行操作并将其放在列表中。我需要做两件事:

  1. 从列表中删除...
  2. 在每个文件上添加当前目录名称。

我可以用循环来做到这一点,或者我可以使用mapand grep

# Map and Grep

my @dir_stack = readdir $dir_fh;;
@dir_stack = grep { !/^\.{1,2}$/ } @dir_stack;
@dir_stack = reverse map { "$cwd/$_" } @dir_stack;
push @stack, @dir_stack;

# Read Loop

opendir $dir_fh, $cwd;
my @dir_stack;
foreach my $file (readdir $dir_fh) {
    next if $file =~ /^\.{1,2}$/;   #Skip "." and ".."
    unshift @dir_stack, "$cwd/$file";
}
push @stack, @dir_stack;

结合grepand怎么样map

 opendir $dir_fh, $cwd;
 my @dir_stack = readdir $dir_fh;;
 @dir_stack = grep { !/^\.{1,2}$/ && {$_ = "$cwd/$_"} } @dir_stack;
 push @stack, reverse @dir_stack;

我希望下周当我查看代码并试图弄清楚发生了什么时,我的代码是可读的。我还需要我的代码高效。

4

3 回答 3

7

$_在 grep 中修改?呸!使用匿名哈希构造函数有什么用?

@dir_stack = grep { !/^\.{1,2}$/ && {$_ = "$cwd/$_"} } @dir_stack;

应该

@dir_stack = map { /^\.\.?\z/ ? () : "$cwd/$_" } @dir_stack;

但我个人发现同时使用 map 和 grep 比组合它们更具可读性。

push @stack,
   reverse
    map "$cwd/$_",
     grep !/^\.\.?\z/,
      readdir $dh;

对 for 的需求reverse相当奇怪,而且它在这里比隐藏为 a 更明显unshift,所以这是另一个好处。

于 2011-12-12T19:54:06.553 回答
2

为了使您的代码更具可读性,您只需要再包含一行:

# exclude '.' and '..', and prepend dir name to each elem in @dir_stack

:-)

于 2011-12-12T19:49:14.297 回答
1

听起来你可能想要glob。虽然我相信它会排除所有以(即隐藏文件)开头的.文件,而不仅仅是.... 当然,路径中不能有空格。

my @stack = glob "$dir_fh/*";

只要你喂它,它就会返回一条路径。

于 2011-12-12T20:13:19.503 回答