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

为什么运行opendir、readdir、stat比Windows dir命令慢?,windows,ubuntu,scripting,perl,Windows,Ubuntu,Scripting,Perl,我有一个Perl脚本,它使用opendir读取目录的内容: opendir ( DIR, $path ) or next; while (my $file = readdir DIR) { 然后我在做: -s$file获取每个文件的大小 (stat($file))[9]获取每个文件的修改时间 我在Windows机器上运行这个,并在Ubuntu 14.04上访问Samba共享 这一切都很正常,但与我在同一文件夹上运行dir列表时相比,进程似乎运行得非常慢 有人知道为什么使用opend

我有一个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
列表花费的时间要长得多吗?如果有什么方法可以改变我的脚本来加快速度的话?

dir会快得多,因为我怀疑它是非常优化的二进制代码,所以它可以快速检索和格式化信息

在您的脚本中,似乎您正在执行几个必须解释的调用,一个用于时间,另一个用于大小。即使Perl中较低的调用是二进制代码,要获得信息也可能需要经过几层。通过保存stat的返回值并访问所需的部分,您可以通过@mob suggestion减少调用次数。例如:

@items = stat($file);
$size = $items[7];
$modified = $items[9];
这将保存其中一个调用,并可能加快脚本速度

如果你想要所有的文件,你可以考虑做一个系统调用来做一个目录命令,并将输出重定向到一个文件,然后你可以解析文件来获取时间和大小的信息。这可能会快一点,具体取决于文件的数量。(/4将是一个4位数的年份,/t:w将是它最后一次写入/修改的时间,/c将去掉大小中的逗号)

然后打开并解析重定向文件以获取所需信息

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
  #.....
}
打开我的$in,“tempList.txt”死“无法打开tempList.txt文件”;
我的@lines=;
收盘价(美元);
chomp(@行);
foreach(@行)
{
下一个if(!(m/^\d{4}\/\d{2}\/\d{2}\s+);不是带文件的行
@部分=拆分('\s+');
#获得你需要的零件(时间和尺寸,可能需要其他零件)
#努力使其达到所需的格式
#.....
}
如果您想处理行,可以添加正则表达式进行匹配,并在测试时根据需要提取项目。这也可以节省一些时间和精力。

根据:

在Win32上
stat()
需要打开文件以确定链接计数并更新可能已通过硬链接更改的属性。将
${^Win32\u SLOPPY\u 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;
}

只要调用
stat
,就可以使用
(stat($file))[7]检索文件大小
,@mob你能告诉我使用stat和-s的区别吗?Thanks@A-Kay像
-s
这样的文件测试操作符实际上在幕后进行
stat
系统调用,因此如果你调用
-s
,然后再调用
stat
,你就在只需要一个系统调用时进行了两个系统调用在:“在Win32上
stat()
需要打开文件以确定链接计数并更新可能已通过硬链接更改的属性。将
${^Win32\u SLOPPY\u stat}
设置为真值会加快
stat()
的速度,因为不执行此操作。”试试看,再加上mob的建议,看看它是否能加快速度。我想打开Samba共享上的文件很费时。@ThisSuitesBlack不感谢这一点-使用WIN32\u SLOPPY\u STAT确实能加快速度。感谢MobThank@Glenn。这里的主要问题是dir没有给我几秒钟的时间,所以我无法将它与当前的epoch进行比较至少,我已经从统计中得到了一些信息。我找到了一个解决方法,通过使用:
forfiles/c“cmd/c echo@file@ftime”
可以给我几秒钟的时间,但是这在UNC路径上不起作用(我的路径是).使用dir是我唯一的出路吗?我发现使用dir的当前方法,速度会降低20倍。非常欢迎@a-Kay。如果您需要使用UNC路径,我会查找net命令,您可以在其中使用net子命令将UNC路径装载为驱动器。这可能对您尝试实现的目标有所帮助。如果您需要dir的速度,可能仅仅用几分钟来比较就足够了吗?@Glenn:这不也可以让文件每行一个文件吗?
@filelist=`ls-1`
我只是觉得在数组中循环更容易,特别是当我必须使用调试器来查看数组中的内容时。@bullush:Tha如果文件数量不多,并且命令是@filelist=
dir/4/t:w/-c$path,则t将起作用,因为它是一台windows计算机。每一行都会有额外的解析。如果您正确的话,可能会快一点,因为您不必从文件中读取。感谢您的教导,而不是激怒我。所以opendir()适用于所有操作系统,是首选方法?因为我只在Linux上工作,所以我使用了我使用的格式。那么
-s$file
后跟
-M
呢?根据
-M
不会进行第二次
统计()
但使用最后一个
stat
的结果,也就是说,也只能调用一次
stat
。@PerlDog只调用一次
stat
,但会给出不同的结果。
-M
返回脚本开始时间减去文件mtime,以天为单位;
stat
返回以纪元秒为单位的mtime。为True,但添加
$^T
将ld not harm.@PerlDog当然,您可以添加一组逻辑来转换
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;
}