perl中递归打印目录路径而不进行文件比较的优化方法
我有一个目录,其中包含多个级别的子目录。我想打印每个目录的路径。 目前,我正在使用perl中递归打印目录路径而不进行文件比较的优化方法,perl,Perl,我有一个目录,其中包含多个级别的子目录。我想打印每个目录的路径。 目前,我正在使用 use File::Find; find( { wanted => \&findfiles, }, $maindirectory); sub findfiles { if (-d) { push @arrayofdirs,$File::Find::dir; } } 但每个子目录在每个级别都包含数千个文件。上面的代码需要花费大量时间
use File::Find;
find(
{
wanted => \&findfiles,
}, $maindirectory);
sub findfiles
{
if (-d) {
push @arrayofdirs,$File::Find::dir;
}
}
但每个子目录在每个级别都包含数千个文件。上面的代码需要花费大量时间来提供结果,因为它会比较每个文件的目录。有没有一种方法可以在不比较文件的情况下获取子目录路径以节省时间或任何其他优化方法
编辑:此问题已部分解决,但由于此解决方案,出现了新问题。我在这里列出了它:如果您在UNIX/Linux平台上,那么您可以尝试将
find$maindirectory-type d
命令的输出读取到您的程序中(请参阅以获取安全的方法)。此命令打印$maindirectory
中的目录名。它更快,因为编译的C程序()完成了所有的艰苦工作。以下脚本应打印找到的所有目录路径
示例脚本:
use strict;
use warnings;
my $maindirectory = '.';
open my $fh, '-|', 'find', $maindirectory, '-type', 'd' or die "Can't open pipe: $!";
while( my $dir = <$fh>) {
print $dir;
}
close $fh or warn "can't close pipe: $!";
使用严格;
使用警告;
我的$maindirectory=';
打开我的$fh、-|、'find'、$main目录、'-type、'd'或die“无法打开管道:$!”;
while(my$dir=){
打印$dir;
}
关闭$fh或警告“无法关闭管道:$!”;
请注意,通过perl调用
find
,然后只打印其输出而不进行任何处理是没有意义的。您也可以在shell本身中运行find$maindirectory-typed
。如果您在UNIX/Linux平台上,那么您可以尝试将find$maindirectory-typed
命令的输出读取到您的程序中(有关安全的方法,请参阅)。此命令打印$maindirectory
中的目录名。它更快,因为编译的C程序()完成了所有的艰苦工作。以下脚本应打印找到的所有目录路径
示例脚本:
use strict;
use warnings;
my $maindirectory = '.';
open my $fh, '-|', 'find', $maindirectory, '-type', 'd' or die "Can't open pipe: $!";
while( my $dir = <$fh>) {
print $dir;
}
close $fh or warn "can't close pipe: $!";
使用严格;
使用警告;
我的$maindirectory=';
打开我的$fh、-|、'find'、$main目录、'-type、'd'或die“无法打开管道:$!”;
while(my$dir=){
打印$dir;
}
关闭$fh或警告“无法关闭管道:$!”;
请注意,通过perl调用
find
,然后只打印其输出而不进行任何处理是没有意义的。您也可以在shell本身中运行find$maindirectory-typed
。POSIX(和libc)函数readdir不为每个目录条目提供文件类型,因此需要对名称执行显式或隐式(如-d
)stat(2)。使用getdents(2)函数可以对其进行优化,但这是特定于Linux的。请参阅。如果您在UNIX/Linux平台上,则可以尝试将find$maindirectory-type d
的输出读取到程序中(请参阅perldoc-f qx
)。这会更快,因为编译的C程序(find
)将完成所有的艰苦工作。类似于@dirs=split/\0/,qx(查找$maindirectory-type d-print0)代码>应该可以工作。另外,您提供的示例代码将每个目录的容器目录保存到数组中,而不是目录本身。我认为这不是故意的。如果你想保存目录名,你应该使用$File::Find::name
。我很好奇,我们谈论的是多少个文件/级别/目录?对于我来说,它在大约3Gb的层次结构上运行不到半秒钟,有近5k个子目录。注意:您不希望$File::Find::dir
在那里,而是希望$File::Find::name
在那里。这里我要说的是20个级别,每个级别都有大约十万个子目录。每个子目录可能包含大约70个文件。POSIX(和libc)函数readdir不提供每个目录条目的文件类型,因此需要在名称上执行显式或隐式(如-d
)stat(2)。使用getdents(2)函数可以对其进行优化,但这是特定于Linux的。请参阅。如果您在UNIX/Linux平台上,则可以尝试将find$maindirectory-type d
的输出读取到程序中(请参阅perldoc-f qx
)。这会更快,因为编译的C程序(find
)将完成所有的艰苦工作。类似于@dirs=split/\0/,qx(查找$maindirectory-type d-print0)代码>应该可以工作。另外,您提供的示例代码将每个目录的容器目录保存到数组中,而不是目录本身。我认为这不是故意的。如果你想保存目录名,你应该使用$File::Find::name
。我很好奇,我们谈论的是多少个文件/级别/目录?对于我来说,它在大约3Gb的层次结构上运行不到半秒钟,有近5k个子目录。注意:您不希望$File::Find::dir
在那里,而是希望$File::Find::name
在那里。这里我要说的是20个级别,每个级别都有大约十万个子目录。每个子目录可能包含大约70个文件。您是否使用find
测试/基准测试以验证运行时是否存在不可忽略的差异?如果Perl程序的大部分时间都花在执行stat
调用上(这些调用由编译的C库处理,很可能与find
使用的库相同),那么很可能差别不大或没有差别。@Dave我用time
做了一些基本的测试。使用问题中给出的示例(经过一些更正后)的脚本将给出real*0m1.623s*user 0m1.030s sys 0m0.590s
。而我的答案中的脚本给出了real*0m0.493s*user 0m0.300s sys 0m0.150s
。两者都位于一个包含870个目录的目录上。我认为我的方法更快,因为它避免了对每个目录项调用所需的函数。谢谢您是否使用find
,测试/基准测试以验证运行时是否存在不可忽略的差异?如果Perl程序的大部分时间用于执行stat
调用(由