find
(für die Prädikate -name
/ -path
standard) verwendet Platzhaltermuster wie Globs (beachten Sie, dass dies {a,b}
kein Glob-Operator ist; nach der Erweiterung erhalten Sie zwei Globs). Der Hauptunterschied ist die Behandlung von Schrägstrichen (und Punktdateien und Verzeichnissen, die nicht speziell behandelt werden find
). *
in Globs werden nicht mehrere Verzeichnisse überspannt. */*/*
Dadurch werden bis zu 2 Verzeichnisebenen aufgelistet. Das Hinzufügen von a entspricht -path './*/*/*'
allen Dateien, die mindestens 3 Ebenen tief sind, und hört nicht auf, find
den Inhalt eines Verzeichnisses in irgendeiner Tiefe aufzulisten.
Für diesen besonderen
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
Ein paar Globs, es ist einfach zu übersetzen. Sie möchten Verzeichnisse in Tiefe 3, damit Sie Folgendes verwenden können:
find . -mindepth 3 -maxdepth 3 \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
(oder -depth 3
mit einigen find
Implementierungen). Oder POSIXly:
find . -path './*/*/*' -prune \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
Welches würde garantieren, dass diese *
und ?
nicht /
Zeichen übereinstimmen konnten .
(Im find
Gegensatz zu Globs würde der Inhalt anderer Verzeichnisse als foo*bar
der im aktuellen Verzeichnis¹ gelesen und die Liste der Dateien nicht sortiert. Wenn wir jedoch das Problem außer Acht lassen, dass das, was übereinstimmt, [A-Z]
oder das Verhalten von *
/ ?
in Bezug auf ungültige Zeichen ist nicht spezifiziert, würden Sie die gleiche Liste von Dateien erhalten).
Wie @muru gezeigt hat , muss auf keinen Fall darauf zurückgegriffen werden, find
wenn nur die Liste der Dateien in mehrere Läufe aufgeteilt werden soll, um das Limit des execve()
Systemaufrufs zu umgehen. Einige Shells wie zsh
(mit zargs
) oder ksh93
(mit command -x
) haben sogar eine eingebaute Unterstützung dafür.
Mit zsh
(deren Globs auch das Äquivalent -type f
und die meisten anderen find
Prädikate haben), zum Beispiel:
autoload zargs # if not already in ~/.zshrc
zargs ./foo*bar/quux[A-Z](|.bak)/pic[0-9][0-9][0-9][0-9]?.jpg(.) -- cmd
( (|.bak)
Ist ein glob Betreiber entgegen {,.bak}
, das (.)
glob Qualifier die äquivalent ist find
‚s -type f
, fügen Sie oN
dort mit der Sortierung wie zu überspringen find
, D
schließen Punkt-Dateien (gilt nicht für diesen glob))
¹ Um find
den Verzeichnisbaum wie Globs zu crawlen, benötigen Sie Folgendes:
find . ! -name . \( \
\( -path './*/*' -o -name 'foo*bar' -o -prune \) \
-path './*/*/*' -prune -name 'pic[0-9][0-9][0-9][0-9]?.jpg' -exec cmd {} + -o \
\( ! -path './*/*' -o -name 'quux[A-Z]' -o -name 'quux[A-Z].bak' -o -prune \) \)
Das heißt beschneiden alle Verzeichnisse auf Stufe 1 bis auf die foo*bar
eine, und alle auf Stufe 2 , mit Ausnahme der quux[A-Z]
oder quux[A-Z].bak
Einsen, und wählen Sie die pic...
diejenigen auf der Ebene 3 (und beschneiden alle Verzeichnisse auf dieser Ebene).
-path
oder zu verwenden-ipath
.find . -path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg'
sollte funktionieren - außer dass es passt/fooz/blah/bar/quuxA/pic1234d.jpg
. Wird das ein Problem sein?