我有一个使用opendir
来读取目录内容的Perl脚本:
opendir ( DIR, $path ) or next;
while (my $file = readdir DIR) {
然后我正在做:
-s $file
获取每个文件的大小(stat($file))[9]
获取每个文件的修改时间我在Windows机器上运行它并在Ubuntu 14.04上访问Samba共享。
这一切都运行良好但与我在同一文件夹上运行dir
列表相比,这个过程似乎运行得非常慢。
有没有人知道为什么使用opendir
需要比dir
列表更长的时间,如果有任何方法可以更改我的脚本以加快速度呢?
答案 0 :(得分:3)
根据perlport:
在Win32
stat()
上需要打开文件以确定链接计数并更新可能已通过硬链接更改的属性。通过不执行此操作,将${^WIN32_SLOPPY_STAT}
设置为真值会加快stat()
。
由于您访问的文件位于Samba共享上,因此打开它们可能相当耗时。此外,-s
在幕后进行stat
系统调用,因此调用-s
后跟stat
是浪费。
以下内容应该更快:
local ${^WIN32_SLOPPY_STAT} = 1;
opendir my $dh, $path or die "Failed to opendir '$path': $!";
while (my $file = readdir $dh) {
my ($size, $mtime) = (stat $file)[7, 9];
say join "\t", $file, $size, $mtime;
}
答案 1 :(得分:0)
Dir会快得多,因为它是二进制代码,我怀疑它是非常优化的,所以它可以快速检索和格式化信息。
在你的脚本中,你似乎正在做几个必须被解释的调用,一个用于时间,另一个用于大小。即使Perl中的较低调用是二进制代码,要获取信息,它可能必须经过多个层。您可以通过保存返回的stat值并访问所需的部分来减少@mob建议的呼叫次数。例如:
@items = stat($file);
$size = $items[7];
$modified = $items[9];
可以保存其中一个调用并可能加快脚本速度。
如果您想要所有文件,可以考虑进行系统调用以执行目录命令并将输出重定向到文件,之后您可以解析文件以获取时间和大小的信息。根据文件的数量,这可能会更快一些。 (/ 4将是一个4位数的年份,/ t:w将是最后一次写入/修改时,/ c将删除大小中的逗号)
system("dir /4 /t:w /-c $path > tempList.txt");
然后打开并解析重定向文件以获取所需信息。
open my $in,"tempList.txt" die "Unable to open file tempList.txt";
my @lines = <$in>;
close($in);
chomp(@lines);
foreach ( @lines )
{
next if ( ! ( m/^\d{4}\/\d{2}\/\d{2}\s+ ); # Not a line with a file
@parts = split('\s+');
# Get the parts you need (time and size, where you may have to some other
# work to get it in the desired format
#.....
}
如果您想要处理该行,可以在测试时添加正则表达式来进行匹配并根据需要提取项目。这也可能节省一些时间和精力。