@ meuhs Ansatz ist ineffizient, da er -maxdepth 1weiterhin findden Inhalt von Verzeichnissen auf Ebene 1 liest, um sie später zu ignorieren. Bei einigen findImplementierungen (einschließlich GNU find) funktioniert dies auch nicht ordnungsgemäß, wenn einige Verzeichnisnamen Folgen von Bytes enthalten, die im Gebietsschema des Benutzers keine gültigen Zeichen bilden (wie bei Dateinamen mit einer anderen Zeichenkodierung).
find . \( -name . -o -prune \) -extra-conditions-and-actions
ist der kanonischere Weg, GNUs -maxdepth 1(oder FreeBSDs -depth -2) zu implementieren .
Im Allgemeinen ist es jedoch -depth 1so, dass Sie es wollen ( -mindepth 1 -maxdepth 1), wie Sie es nicht wollen .(Tiefe 0), und dann ist es noch einfacher:
find . ! -name . -prune -extra-conditions-and-actions
Denn -maxdepth 2das wird:
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Und hier stoßen Sie auf die Probleme mit ungültigen Charakteren.
Wenn Sie beispielsweise ein Verzeichnis mit dem Namen haben Stéphane, das éjedoch im Zeichensatz iso8859-1 (auch bekannt als latin1) (0xe9-Byte) codiert ist, wie es in Westeuropa und den USA bis Mitte der 2000er Jahre am häufigsten vorkam, dann ist dieses 0xe9-Byte kein gültiges Zeichen in UTF-8. Also, in UTF-8 - Sprachumgebungen, die *Platzhalter (mit einigen findImplementierungen) nicht übereinstimmen Stéphaneals *0 oder mehr Zeichen und 0xE9 ist kein Charakter.
$ locale charmap
UTF-8
$ find . -maxdepth 2
.
./St?phane
./St?phane/Chazelas
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
$ find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St?phane/Chazelas/age
./St?phane/Chazelas/gender
./St?phane/Chazelas/address
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
My find(wenn die Ausgabe an ein Terminal geht) zeigt dieses ungültige 0xe9-Byte wie ?oben an. Sie können sehen, das St<0xe9>phane/Chazelaswar nicht pruned.
Sie können dies umgehen, indem Sie Folgendes tun:
LC_ALL=C find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Beachten Sie jedoch, dass dies Auswirkungen auf alle Gebietsschemaeinstellungen findund auf alle ausgeführten Anwendungen hat (z. B. über die -execPrädikate).
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
Jetzt bekomme ich wirklich eine -maxdepth 2aber beachten Sie, wie die in UTF-8 richtig codierten é in der zweiten Stéphane ??als die 0xc3 0xa9-Bytes (betrachtet als zwei einzelne undefinierte Zeichen in der C-Ländereinstellung) der UTF-8-Codierung von é angezeigt werden Nicht druckbare Zeichen im Gebietsschema C.
Und wenn ich ein hinzugefügt hätte -name '????????', hätte ich die falsche Stéphane (die in ISO8859-1 codierte) bekommen.
Um sie auf beliebige Pfade anzuwenden ., gehen Sie wie folgt vor:
find some/dir/. ! -name . -prune ...
für -mindepth 1 -maxdepth 1oder:
find some/dir/. \( ! -path '*/./*/*' -o -prune \) ...
für -maxdepth 2.
Ich würde immer noch Folgendes tun:
(cd -P -- "$dir" && find . ...)
Erstens, weil dadurch die Pfade kürzer werden, wodurch es weniger wahrscheinlich ist, dass sie auf einen zu langen Pfad oder eine zu lange Liste vonfind Argumenten stoßen, sondern auch die Tatsache umgangen wird , dass willkürliche Pfadargumente (außer -fmit FreeBSD find) nicht unterstützt werden, da sie ersticken Werte $dirwie !oder -print...
Die -oKombination mit Negation ist ein häufiger Trick, um zwei unabhängige Sätze von -condition/ -actionin auszuführen find.
Wenn Sie in -action1Dateikonferenzen -condition1und unabhängig -action2in Dateikonferenzen ausführen möchten -condition2, können Sie Folgendes nicht ausführen :
find . -condition1 -action1 -condition2 -action2
As -action2würde nur für Dateien ausgeführt, die beide Bedingungen erfüllen .
Noch:
find . -contition1 -action1 -o -condition2 -action2
Wie -action2würde für Dateien nicht ausgeführt werden, der treffen beide Bedingungen.
find . \( ! -condition1 -o -action1 \) -condition2 -action2
funktioniert so \( ! -condition1 -o -action1 \), wie es für jede Datei auf true aufgelöst würde . Dies setzt voraus , dass -action1eine Aktion (wie ) immer true zurückgibt . Für Aktionen wie diese , die möglicherweise false zurückgeben , möchten Sie möglicherweise eine andere hinzufügen, bei der harmlos ist, die jedoch true zurückgibt , wie in GNU oder oder (beachten Sie jedoch das Problem mit ungültigen Zeichen oben).-prune-exec ... {} +-exec ... \;-o -something-something-truefind-links +0-name '*'
-depth -2,-depth 1... Ansatz könnte als besser angesehen werden als GNU's-maxdepth/-mindepth