4

次のようなものを使用して、特定のディレクトリ内のサブディレクトリのリストを取得しようとしています:

#!/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。上記のことは可能ですか?サブディレクトリを一覧表示する別の方法を使用する必要がありますか? 汚染モードについて本当に理解しておくべき明らかなことを完全に誤解していますか?

4

1 に答える 1

5

(編集!) さて、ロジックは、次のようにスローするとうまくいくことを示唆しています:

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

これにより、File::Find の汚染モード機能を、そのモジュールの関数に直接引数を渡すことによって使用できますfind()。ちなみに、File::Find は、演算子$untaint_patternを使用して設定する必要があると述べています。qr//たとえば、デフォルト値は

$untaint_pattern = qr|^([-+@\w./]+)$|

しかし、これはうまくいきません!実際、あなたの問題は File::Find::Rule の既知のバグです。(たとえば、ここにCPANDebianのバグ レポートがあります。) バグ修正が必要な場合は、これらのバグ レポートの両方にパッチがあります。

制限された環境にいる場合にできることの 1 つは、本質的にパッチを自分でコードに実装することです。たとえば、すべてを 1 つのファイルに保持したい場合は、以下の大きなコード ブロックを の後に追加できますuse File::Find::Rule。これは非常に迅速な修正であり、最適ではない可能性があることに注意してください。ファイル名にスペースが含まれているなどの理由でうまくいかない場合は、qr|^([-+@\w./]+)$|使用するパターンを変更してください。

最後に、コード構成をもう少し良くしたい場合は、これを MyFileFindRuleFix などと呼ばれる別のパッケージにダンプしたい場合があることに注意してuseくださいFile::Find::Rule

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' $@";
    my $cwd = getcwd;
    # Untaint it
    if ( $cwd =~ qr|^([-+@\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;
于 2009-01-12T01:08:15.207 に答える