我正在尝试获取按修改日期排序的文件列表。我修改了 * Sort Directory and list files based on date and time * 中的示例程序并尝试运行它。
sub get_sorted_files {
my $path = shift;
opendir my($dir), $path or die "can't opendir $path: $!";
my %hash = map {$_ => (stat($_))[9]}
map { "$dir$_" }
grep { m/.*/i }
readdir $dir;
closedir $dir;
return %hash;
}
my %files = get_sorted_files(".");
foreach my $keys (sort{$files{$a} <=> $files{$b}} keys %files) {
print "$keys\t", scalar localtime($files{$keys}), "\n";
}
我正在我的Windows XP 32位计算机上运行这个程序,使用的是Strawberry Perl版本5.12.1.0。
Windows上的目录列表为:
输出为:
输出对我来说没有多大意义。这段代码出了什么问题?foreach
循环对文件列表的排序到底是如何的?
5条答案
按热度按时间sqyvllje1#
该代码至少有两个问题。下面是一个更好的版本:
首先,您将原始代码中的
$dir
重命名为$path
,但没有在map
行中更改它。这就是GLOB(0x...)的来源。其次,所有修改日期都显示为“Wed Dec 31 16:00:00 1969”,因为您传递给
stat
的路径名不正确。(stat($_))[9]
返回一个空列表(因为您要查找类似GLOB(0x3f9b38)status.txt
的文件,而不是正确的路径名),因此散列实际上包含了文件名作为键和值。第一个文件名是键,第二个是它的值,第三个是下一个键,依此类推。localtime
将文件名转换为数字(生成0),然后将纪元时间0(1970年1月1日0:00:00 UTC)转换为您的时区。第三,它期望
$path
以目录分隔符结尾,而您传递的是"."
,您需要传递"./"
,或者更好的是,修复它,以便函数在需要时附加分隔符。第四,
grep
不再执行任何操作,应该将其删除(在原始代码中,它只选择某些文件名,但您更改了模式以匹配任何内容)。至于它如何排序文件名:
get_sorted_files
返回路径名和修改时间的列表,您可以将其存储到%files
散列中。keys %files
返回键(文件名)的列表,并根据关联值(修改时间)的数值比较对它们进行排序。x7yiwoj42#
使用Perl的sort函数,它速度更快,而且不需要哈希就能得到你想要的东西。
文件大小,然后是文件期限:
@s =排序{-s $a〈=〉-s $B||-M $B〈=〉-M $a} @a
了解了以上内容,我们可以说如下的话:
wgx48brx3#
在
get_sorted_files
中,$dir
是一个glob,而不是目录名。也许你指的是$path
?pes8fvy94#
对于非常大的目录,您可能会发现Perl比使用本地工具进行排序要慢得多,例如,在我的机器上,对于一个巨大的(341 k个文件)目录,这需要大约1.5分钟:
但是上述解决方案中的代码(使用
opendir
和sort -M
)要多花30-45秒,不仅速度快得多,而且还可以避免Perl将整个数组存储在内存中,这本身就是一种优势。请注意,以上是在一个相当高端的Linux刀片系统上,因此每台计算机/OS的YMMV...
juud5qan5#
使用一行程序: