8

当我在 Perl 中使用opendirreaddir和读取目录时closedir,该readdir函数似乎没有以任何特定顺序读取文件(我可以说)。

我正在阅读一个目录,其中包含以纪元时间戳命名的子目录:

1224161460
1228324260
1229698140

我想按数字顺序读取这些目录,这会将最旧的目录放在第一位。

当我使用readdir时,它读取的第一个是 1228324260,它是中间的。我知道我可以将目录内容放在一个数组中并对数组进行排序,但是我可以传递一个选项来readdir按排序顺序读取吗?或者也许比将所有内容推入数组并对数组进行排序更优雅的方式来实现这一点?可能也有模块可以做到这一点,但是很难在我们的环境中安装模块,所以除非它是一个内置模块,否则我宁愿不使用模块......

谢谢!

编辑 按要求,我发布了我正在使用的代码:

opendir( my $data_dh, $data_dir ) or die "Cannot open $data_dir\n";
while ( my $name = readdir($data_dh) ) {
    next if ( $name eq '.' or $name eq '..' );
    my $full_path = "${data_dir}/${name}";
    next unless ( -d $full_path );
    process_dir($full_path);
}
closedir($data_dh);
4

3 回答 3

13

readdir可以在数组上下文中调用,所以只需这样做:

opendir( my $data_dh, $data_dir) or die "Cannot open $data_dir\n";
my @files = sort { $a <=> $b } readdir($data_dh);
while ( my $name = shift @files ) {
...
于 2009-01-12T17:42:40.020 回答
5

你可以用一点 Glob 魔法来尝试一下,glob 似乎以一种排序的方式运行,所以这个:

#  Glob in scalar context iterates the result set internally
while( defined( my $dir = glob($dir . '/*' ) ) ){ 
     print $dir, "\n";
    # $dir is fed ordered and with full names. 
}

或者

# Glob in list context returns all results. 
for( glob($dir.'/*' ) ){ 
  print $dir , "\n";
  # also ordered. 
}

应该管用。小心 glob,因为:

 for(0..20){ 
   printf "%30s|%30s\n", glob($dir.'/*' ), glob($dir.'/*' );
 }

做了一些半神奇的事情,并在每行上打印 dir 内容两次。IE:

/foo/bar/a  |  /foo/bar/a
/foo/bar/b  |  /foo/bar/b
/foo/bar/c  |  /foo/bar/c
/foo/bar/d  |  /foo/bar/d
于 2009-01-12T18:00:38.080 回答
5

只需sort在要重新排序的任何列表运算符前面加上一个。您也不需要将结果存储在数组中。您可以使用foreach

opendir my($dh), $dirname or die "Could not open directory [$dirname]: $!";

foreach my $file ( sort { $a <=> $b } readdir $dh )
    {
    ...
    }
于 2009-01-12T19:10:15.287 回答