@ meuhs Ansatz ist ineffizient, da er -maxdepth 1
weiterhin find
den Inhalt von Verzeichnissen auf Ebene 1 liest, um sie später zu ignorieren. Bei einigen find
Implementierungen (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 1
so, 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 2
das 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 find
Implementierungen) nicht übereinstimmen Stéphane
als *
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/Chazelas
war nicht prune
d.
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 find
und auf alle ausgeführten Anwendungen hat (z. B. über die -exec
Prä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 2
aber 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 1
oder:
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 -f
mit FreeBSD find
) nicht unterstützt werden, da sie ersticken Werte $dir
wie !
oder -print
...
Die -o
Kombination mit Negation ist ein häufiger Trick, um zwei unabhängige Sätze von -condition
/ -action
in auszuführen find
.
Wenn Sie in -action1
Dateikonferenzen -condition1
und unabhängig -action2
in Dateikonferenzen ausführen möchten -condition2
, können Sie Folgendes nicht ausführen :
find . -condition1 -action1 -condition2 -action2
As -action2
würde nur für Dateien ausgeführt, die beide Bedingungen erfüllen .
Noch:
find . -contition1 -action1 -o -condition2 -action2
Wie -action2
wü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 -action1
eine 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
-true
find
-links +0
-name '*'
-depth -2
,-depth 1
... Ansatz könnte als besser angesehen werden als GNU's-maxdepth
/-mindepth