我有一个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 #..... }
在测试是否要处理该行时,可能需要添加正则表达式来进行匹配和拉出项目。 这可能会节省一些时间和精力。