Frage

Ich versuche, eine Liste von Unterverzeichnissen in einem bestimmten Verzeichnis zu erhalten, mit so etwas wie folgt aus:

#!/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);

Dies ist jedoch Laufen gibt das Ergebnis:

  

Insecure dependency in chdir while running with -T switch

Ich verstehe, dass File::Find Optionen für den Umgang mit Taint-Modus hat, aber ich kann ‚t scheinen ein Äquivalent in File::Find::Rule . Ist es möglich, die oben genannten zu tun? Soll ich eine alternative Methode für die Auflistung Verzeichnisse verwenden? Bin ich völlig Missverständnis etwas offensichtlich, dass ich wirklich über Taint-Modus verstehen sollte?

War es hilfreich?

Lösung

(! Bearbeiten ) Okay, Logik würde vorschlagen, dass in den folgenden werfen funktionieren würde:

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

Auf diese Weise können Sie die Taint-Modus Funktionen von Datei verwenden, indem :: Find Argumente direkt an die zugehörigen Busklemmenbeschreibung find() Funktion übergeben. Übrigens File :: Find erwähnt, dass ein $untaint_pattern unter Verwendung des qr// Betreiber setzen soll. Zum Beispiel ist der Standardwert

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

Doch , das funktioniert nicht! In der Tat ist das Problem ein bekannter Fehler in File :: Find :: Rule. (Zum Beispiel sind hier die CPAN und Debian Bug-Report.) Wenn Sie einen Bugfix mögen, dann beide diese Fehlerberichte haben Patches.

Wenn Sie in einer eingeschränkten Umgebung sind, eine Sache, die Sie tun können, ist implementieren im Wesentlichen den Patch selbst in Ihrem Code. Zum Beispiel, wenn Sie alles in einer Datei behalten möchten, können Sie den großen Code-Block unten nach use File::Find::Rule hinzufügen. Beachten Sie, dass dies eine sehr schnelle Lösung und suboptimal sein kann. Wenn es nicht für Sie arbeiten (zum Beispiel, weil Sie Leerzeichen in Dateinamen haben), das Muster qr|^([-+@\w./]+)$| ändern, die verwendet wird.

Beachten Sie schließlich, dass, wenn Sie Ihren Code Organisation wollen ein bisschen besser sein, sollten Sie diese in einem separaten Paket dump, vielleicht MyFileFindRuleFix oder etwas genannt, dass man nach use selbst immer 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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top