为什么运行opendir,readdir,stat比Windows dir命令慢?

我有一个Perl脚本使用opendir来读取目录的内容:

 opendir ( DIR, $path ) or next; while (my $file = readdir DIR) { 

然后我在做:

  • -s $file来获取每个文件的大小
  • (stat($file))[9]来获取每个文件的修改时间

我从Windows机器上运行这个程序,并在Ubuntu 14.04上访问Samba共享。

这一切都工作正常,但进程似乎运行速度相比,当我在同一个文件夹上运行一个dir列表。

有谁知道为什么使用opendir需要比dir列表更长的时间,如果有任何方法,我可以改变我的脚本来加快速度?

根据perlport :

在Win32上, stat()需要打开文件来确定可能通过硬链接改变的链接数量和更新属性。 将${^WIN32_SLOPPY_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; } 

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 #..... } 

在测试是否要处理该行时,可能需要添加正则表达式来进行匹配和拉出项目。 这可能会节省一些时间和精力。