opendir und ./..
Manfred Kuhn
- perl
0 Beat0 Manfred Kuhn0 Alexander (HH)0 hotti
hi!
kurze frage: ich lasse mir mit opendir sortiert ein verzeichnis in ein array geben lassen mit welchem ich dann weiterarbeiten möchte. funktioniert perfekt, würden nicht auch ./.. Verzeichnisse aufgelistet werden.
Also es sieht so aus:
.
..
datei.txt
datei2.txt
usw.
ich habe auch versucht mit s/^..$//; versucht die zu entfernen, klappt aber dafür bleibt eine leere Zeile welche ich nicht wegbekomme. Wie kann ich ./.. aus meinem Array entfernen?
danke
mfg
kurze frage: ich lasse mir mit opendir sortiert ein verzeichnis in ein array geben lassen mit welchem ich dann weiterarbeiten möchte. funktioniert perfekt, würden nicht auch ./.. Verzeichnisse aufgelistet werden.
Also es sieht so aus:
.
..
datei.txt
datei2.txt
usw.ich habe auch versucht mit s/^..$//; versucht die zu entfernen, klappt aber dafür bleibt eine leere Zeile welche ich nicht wegbekomme. Wie kann ich ./.. aus meinem Array entfernen?
z.B. mit grep(/[1]/) @array
mfg Beat
^. ↩︎
hallo beat. danke.
z.B. mit grep(/[1]/) @array
leider funktioniert das nicht bei mir, ich bekomme die Meldung "not enought arguments for grep at C:\Pfad near "/[2]/) "
Was mach ich falsch?
Beat hatte die falschen Klammern:
grep {/[3]/} @ary;
Hotti
Moin Moin!
my @dateien = grep{ not /^./ } readdir DIR;
geht natürlich auch.
Nö, frißt zu viel weg, siehe mein Posting von 08:11.
So mach ich das, wenn ich nicht globbe:
chdir($dir);
my @files = <*.gif>;
Lustigerweise genau das selbe Problem. Die PerlFAQ beschreibt ein ähnliches Problem in http://perldoc.perl.org/perlfaq5.html#Why-doesn't-glob("*.*")-get-all-the-files?. glob findet keinen einzigen Verzeichniseintrag, der mit einem Punkt anfängt -- außer man schreibt den Punkt explizit rein.
chdir ist übrigens unnötig, glob("$dir/*.gif")
funktioniert genauso und liefert das Verzeichnis gleich mit, im Gegensatz zu readdir. Mein Problem mit glob ist, dass glob nicht sonderlich portabel ist und bei alten Perl-Versionen(?) einen Helfer-Prozess startet. Und das Pattern muß in der jeweiligen Shell- statt RegExp-Syntax angegeben werden.
Alexander
hi,
chdir ist übrigens unnötig,
glob("$dir/*.gif")
funktioniert genauso und liefert das Verzeichnis gleich mit, im Gegensatz zu readdir.
Ja, das ist richtig. Für meine Kdo-Zeilen-Perl-Scripts benutze ich gerne das Modul Cwd.pm und erhalte mit getcwd() die current work directory direkt und ohne File::Basename-Parserei gleich auf $dir.
Mein Problem mit glob ist, dass glob nicht sonderlich portabel ist und bei alten Perl-Versionen(?) einen Helfer-Prozess startet. Und das Pattern muß in der jeweiligen Shell- statt RegExp-Syntax angegeben werden.
Meine Perl-Scripts, die so ins FS greifen, laufen alle lokal und auf der Kdo-Zeile, mit glob habe ich dabei keine Schmerzen, die ich vermutlich auch hätte, wenn sowas auf einem produktiven Webserver laufen würde, dessen Administration nicht in meiner Hand liegt.
Hotti
FUD-Zerst(?:reu|ör)ung:
Mein Problem mit glob ist, dass glob nicht sonderlich portabel ist
und bei alten Perl-Versionen(?) einen Helfer-Prozess startet
Man kann glob ohne diese Bedenken einsetzen (ich persönlich ziehe immer File::Next vor, da besseres Interface, aber das nur nebenbei).
glob funktioniert überall dort, wo Perl funktioniert, weil die Funktionalität schon vor 10 Jahren (tiefstes Pleistozän, wenn man bedenkt, dass Perl ~20 Jahre alt ist) komplett nach Core portiert wurde. Daher liefert glob auf allen Plattformen jeweils das gleiche Ergebnis.
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
^. ↩︎
moin,
Das ist nun wirklich eine oft gestellte Frage, aber lustigerweise finde ich in der Perl-FAQ keine fertige Antwort. Schade eigentlich.
Danke für Deine Beispiele!!! Feine Sache!
Horst <*.huhn>