Alexander (HH): opendir und ./..

Beitrag lesen

Moin Moin!

z.B. mit grep(/[1]/) @array

Sorry, das ist nicht das, was Manfred haben will. Du schmeißt sehr umständlich ALLE Verzeichnisinhalte weg, die mit einem Punkt beginnen. In meinem $HOME wären das 75 Verzeichniseinträge.

grep ist der richtige Weg, aber der Filter ist falsch.

  
grep { !/^\.{1,2}$/ } readdir $d  

schmeißt nur die Elemente aus der Liste, die aus exakt einem oder zwei Punkten bestehen -- . und ..

Das ist nun wirklich eine oft gestellte Frage, aber lustigerweise finde ich in der Perl-FAQ keine fertige Antwort. Schade eigentlich.

Oh, und natürlich gibt es mehr als einen Weg, das Problem zu lösen.

  
grep { !/^\.\.?$/ } readdir $d  

Genau das gleiche Spiel, nur anders formuliert. Entfernt alle Elemente aus der Liste, die aus exakt einem Punkt bestehen, optional gefolgt von einem weiteren Punkt.

  
grep { ($_ ne '.') and ($_ ne '..') } readdir $d  

Ohne RegExp, dafür etwas mehr Tipparbeit. Und für Leute mit RegExp-Schwäche wahrscheinlich die lesbarste. Ich denke auch, dass diese Variante vielleicht sogar einen Tick schneller als die RegExp ist, weil hier nur zwei einfache String-Vergleiche statt eines RegExp-Laufs stattfinden.

  
grep { !(($_ eq '.') or ($_ eq '..')) } readdir $d  

Gleiches Spiel, nur anders formuliert.

Ein anderes gängiges Ideom ist eine while-Schleife, die läuft, bis readdir nichts mehr liefert. Das spart etwas Speicher, weil das Verzeichnis Eintrag für Eintrag verdaut wird statt auf einen Schlag. In der Regel ist der Unterschied aber minimal. Diese while-Schleife überspringt die unerwünschten Einträge einfach mit next.

  
while (my $name=readdir $d) {  
    next if ($name eq '.') or ($name eq '..');  
    # Alternativ:  
    next if $name=~/^\.{1,2}$/;  
    # Alternativ:  
    next if $name=~/^\.\.?$/;  
    mach_was_mit($name);  
}  

Gängige Erweiterung: Prüfen des Eintrag-Typs.

  
while (my $name=readdir $d) {  
    next if $name=~/^\.{1,2}$/; # . und .. sind unerwünscht  
    next unless -f("$dirname/$name"); # ebenso alle nicht regulären Dateien (Symlinks, Verzeichnisse, Devices, ...)  
    #               ^-- readdir() liefert nur den Eintrag, NICHT den Namen des Verzeichnisses.  
    #               Wenn man nicht das aktuelle Verzeichnis liest, ist das ein Unterschied!  
    next unless -s(_) && -r(_); # leere und nicht lesbare Dateien sind auch unerwünscht.  
    # _ spart den erneuten stat()-Aufruf, siehe perldoc perlfunc.  
    mach_was_mit($name);  
}  

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".

  1. ^. ↩︎