我该如何在Perl中循环遍历目录中的文件?

29

1
这个问题不是重复了这个吗?https://dev59.com/mHNA5IYBdhLWcg3wNrEy - Leonardo Herrera
1
@Leonardo Herrera 确实如此。抱歉,我没记住那个问题。投票关闭。 - Sinan Ünür
我不明白这是如何成为重复问题的。该问题询问如何循环遍历目录中的文件,而被标记为“重复”的问题则询问如何列出目录中的所有文件。显然两者不同。为什么要标记为重复? - CJ7
3个回答

53
#!/usr/bin/perl -w

my @files = <*>;
foreach my $file (@files) {
  print $file . "\n";
}

在哪里

 @files = <*>;

可以

 @files = </var/www/htdocs/*>;
 @files = </var/www/htdocs/*.html>;

等等之类的。


这将不会在GNU/Linux和可能的其他类似操作系统上列出隐藏文件(以点开头的文件)。 - josch

23

享受。

opendir(DH, "directory");
my @files = readdir(DH);
closedir(DH);

foreach my $file (@files)
{
    # skip . and ..
    next if($file =~ /^\.$/);
    next if($file =~ /^\.\.$/);

    # $file is the file used on this iteration of the loop
}

1
谢谢!我会用next if ($file =~ /^.+$/);,这样就避免了第二个语句的出现 ;)。 - ashraf
2
@ashraf 正则表达式应该是 /^.+$/ 而不是 /^.+$/。 - Rauf
@Rauf 是的,我认为你是对的! :) - ashraf

13
你可以使用readdirglob来实现。或者,你可以使用像Path::Class这样的模块:

通常情况下,children() 不会包含当前目录和上级目录中的 . 和 ..(或非Unix系统中对应的条目),因为这就像是我自己的爷爷的生意。如果你想要包含这些特殊条目的所有目录条目,请将 all 参数设置为 true 值:

@c = $dir->children(); # Just the children
@c = $dir->children(all => 1); # All entries

此外,还有一个no_hidden参数,它将排除所有通常“隐藏”的条目 - 在Unix上,这意味着排除所有以点(.)开头的条目:

@c = $dir->children(no_hidden => 1); # Just normally-visible entries

或者,Path::Tiny

@paths = path("/tmp")->children;
@paths = path("/tmp")->children( qr/\.txt$/ );
返回一个列表,其中包含目录中所有文件和子目录的 Path::Tiny 对象。自动排除"."".."
如果提供了可选的 qr// 参数,则仅返回与给定正则表达式匹配的子名称对象。只使用基本名称进行匹配。
@paths = path("/tmp")->children( qr/^foo/ );
# matches children like the glob foo*
将目录条目列表获取到数组中会浪费一些内存(相对于逐个获取文件名),但是仅有几百个文件的情况下,这不太可能成为问题。
Path::Class可在*nix和Windows以外的操作系统上使用。另一方面,据我所知,它的实例使用的内存比Path::Tiny实例多。
如果内存是一个问题,最好在while循环中使用readdir。

read_dir会为您删除.和..,如果需要,还可以将目录前缀添加到文件名中。 - Matthew Lock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接