2009-01-12 29 views
4

我想使用類似以下以獲得給定目錄的子目錄列表:如何在污染模式下使用File :: Find :: Rule?

#!/usr/bin/perl -wT 
use strict; 
use warnings; 

use File::Find::Rule; 
use Data::Dumper; 

my @subdirs = File::Find::Rule->maxdepth(1)->directory->relative->in('mydir'); 

print Dumper(@subdirs); 

然而,運行此給出結果:

Insecure dependency in chdir while running with -T switch

我明白File::Find有處理污點模式的選項,但我似乎無法在File::Find::Rule中找到相應的選項。是否有可能做到以上?我應該使用另一種方法列出子目錄嗎?我完全誤解了一些顯而易見的東西,我真的應該瞭解污染模式嗎?

回答

5

(!編輯)好吧,邏輯會建議在以下扔將工作:

->extras({untaint => 1, untaint_pattern => $untaint_pattern, untaint_skip => 1}) 

這允許您使用文件的污點模式的特點::直接傳遞參數給查找模塊的find()功能。順便提一句,File :: Find提到應該使用qr//運算符來設置$untaint_pattern。例如,默認值是

$untaint_pattern = qr|^([[email protected]\w./]+)$| 

然而,這也不行!事實上,你的問題是File :: Find :: Rule中的一個已知錯誤。 (例如,這裏是CPANDebian錯誤報告。)如果你想要一個錯誤修正,那麼這兩個錯誤報告都有補丁。

如果您處於受限制的環境中,您可以做的一件事就是在您的代碼中自行實施修補程序。例如,如果要將所有內容保存在一個文件中,則可以在use File::Find::Rule之後添加下面的大代碼塊。請注意,這是一個非常快速的修復,可能不是最理想的。如果它不適合您(例如,因爲您的文件名中有空格),請更改使用的模式qr|^([[email protected]\w./]+)$|

說明最後,如果你希望你的代碼組織好一點,你可能要轉儲到一個單獨的包本,File::Find::Rule本身也許以後叫MyFileFindRuleFix什麼的,你總是use

package File::Find::Rule; 
no warnings qw(redefine); 
sub in { 
    my $self = _force_object shift; 

    my @found; 
    my $fragment = $self->_compile($self->{subs}); 
    my @subs = @{ $self->{subs} }; 

    warn "relative mode handed multiple paths - that's a bit silly\n" 
     if $self->{relative} && @_ > 1; 

    my $topdir; 
    my $code = 'sub { 
     (my $path = $File::Find::name) =~ s#^(?:\./+)+##; 
     $path = "." if ($path eq ""); # See Debian bug #329377 
     my @args = ($_, $File::Find::dir, $path); 
     my $maxdepth = $self->{maxdepth}; 
     my $mindepth = $self->{mindepth}; 
     my $relative = $self->{relative}; 

     # figure out the relative path and depth 
     my $relpath = $File::Find::name; 
     $relpath =~ s{^\Q$topdir\E/?}{}; 
     my $depth = scalar File::Spec->splitdir($relpath); 
     #print "name: \'$File::Find::name\' "; 
     #print "relpath: \'$relpath\' depth: $depth relative: $relative\n"; 

     defined $maxdepth && $depth >= $maxdepth 
      and $File::Find::prune = 1; 

     defined $mindepth && $depth < $mindepth 
      and return; 

     #print "Testing \'$_\'\n"; 

     my $discarded; 
     return unless ' . $fragment . '; 
     return if $discarded; 
     if ($relative) { 
      push @found, $relpath if $relpath ne ""; 
     } 
     else { 
      push @found, $path; 
     } 
    }'; 

    #use Data::Dumper; 
    #print Dumper \@subs; 
    #warn "Compiled sub: '$code'\n"; 

    my $sub = eval "$code" or die "compile error '$code' [email protected]"; 
    my $cwd = getcwd; 
    # Untaint it 
    if ($cwd =~ qr|^([[email protected]\w./]+)$|) { 
     $cwd = $1; 
    } else { 
     die "Couldn't untaint \$cwd: [$cwd]"; 
    } 
    for my $path (@_) { 
     # $topdir is used for relative and maxdepth 
     $topdir = $path; 
     # slice off the trailing slash if there is one (the 
     # maxdepth/mindepth code is fussy) 
     $topdir =~ s{/?$}{} 
      unless $topdir eq '/'; 
     $self->_call_find({ %{ $self->{extras} }, wanted => $sub }, $path); 
    } 
    chdir $cwd; 

    return @found; 
} 
use warnings; 
package main; 
+0

謝謝,這有很大的幫助。由於我處於一個稍微受限的環境中(並且無法獲得補丁),您能否提出一種替代方法來獲得相同的結果? – 2009-01-12 01:43:26

相關問題