2016-11-30 57 views
1

我是Perl新手。 我想在包含多個子文件夾,子子文件夾和大量文件的大型目錄樹中遞歸搜索pdf文件。 我正在使用File::Find::Rule來實現這一點。但是,性能影響是巨大的。 該腳本需要花費大量時間進行搜索。Perl:在大型目錄結構中搜索pdf文件recursivley

從我的Perl腳本

段:

@folders = File::Find::Rule -> file -> name('*.[pP][dD][fF]') -> in($folderPath); 

是否有任何其他的方式來實現這一目標,而不會影響性能?

任何幫助將不勝感激。

+1

(非perl)命令如何比較查找start_dir -name *。[pP] [dD] [fF]「?那是否比你的Perl腳本更快? – PerlDuck

回答

1

你可以嘗試使用ag代替:

my $cmd = 'ag -g "\.[pP][dD][fF]$" ' . $folderPath; 
chomp(my @files = qx/$cmd/); 
0

嘗試子程序這遞歸搜索子目錄。在我的例子中,你必須傳遞你的起始目錄和一個數組(通過引用,即:\ @ name_of_array),這些數據將填充子目錄。我希望它可以提高性能,但我不知道這一點

sub list_dirs 
{ 
    my ($dir, $dirs) = @_; 
    opendir(D, $dir) || die "cannot open directory $dir\n\n"; 
    my @tmp_dirs = readdir(D); 
    closedir(D); 
    foreach my $tmp_dir (@tmp_dirs) 
    { 
     if (-d "$dir/$tmp_dir") 
     { 
      next if ($tmp_dir eq ".."); 
      next if ($tmp_dir eq "."); 
      push @$dirs, "$dir/$tmp_dir"; 
      list_dirs("$dir/$tmp_dir", $dirs); 
     } 
    } 
    return $dirs; 
} 
2

你的問題很簡單:與其看着,因爲它遇到的每個候選文件,你都在等待File::Find::Rule建立一個列表,並將其返回您。這意味着您將一直等待,直到它查看了該樹下的所有文件。而且,從冷啓動和足夠數量的文件開始,在顯示結果之前需要很長時間。

相反,您可以使用底層的File::Find來檢查遇到的每個文件。您可能還會發現有用的Path::Tiny's iterator

您不會更改訪問樹下每個文件所需的時間。但是,通過處理遇到的每個文件,您將1)減少程序的內存佔用量,因爲不必構建巨大的列表;和2)你將看到更快的結果。

像這樣的事情讓你開始:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use File::HomeDir qw(my_documents); 
use Path::Tiny; 

my $it = path(my_documents)->iterator({ recurse => 1 }); 

while (my $path = $it->()) { 
    return $path->is_file and $path =~/[.] pdf \z/ix; 
    do_something_with_pdf($path); 
} 

sub do_something_with_pdf { 
    print $_[0]->canonpath, "\n"; 
} 

如果你不喜歡的File::Find::Rule規則部分,你可能更喜歡Path::Iterator::Rule。重要的規則是避免在開始處理之前等待構建可能非常大的列表。

但是,如果您只需要一個快速的方法來獲取所有PDF文件的列表,就應該考慮使用The Silver Searcher