Unterschiedliches Verhalten zwischen find -exec und Piping durch xargs

Unterschiedliches Verhalten zwischen find -exec und Piping durch xargs

Ich wollte rekursiv chmod go+win einem bestimmten Ordner einschließlich versteckter Dateien ausführen und habe zuerst versucht

find . -name ".*" -o -name "*" -exec chmod go+w {} \;

aber ich habe festgestellt, dass es keine Auswirkungen auf versteckte Dateien hatte. Um mich selbst zu überprüfen, habe ich einfach

find . -name ".*" -o -name "*"

und die versteckten Dateien wurden aufgelistet. Mir ist auch aufgefallen, dass, wenn ich den -o -name "*"Teil ausschließe, die versteckten Dateien chmod werden (aber natürlich nicht versteckte Dateien ausschließen). Mein letzter Versuch war, stattdessen xargs zu verwenden

find . -name ".*" -o -name "*" | xargs chmod go+w

was schließlich wie erwartet funktionierte. Was mache ich im ersten Snippet falsch?

Red Hat Enterprise Linux Server Version 6.8 (Santiago)

GNU Bash, Version 4.3.42(1)-Release (x86_64-unknown-linux-gnu)

Antwort1

Die Lösung besteht darin, die beiden Namenstests mit Klammern miteinander zu verbinden.

Um dies zu veranschaulichen, betrachten wir ein Verzeichnis mit drei regulären Dateien:

$ ls -a
.  ..  .hidden1  .hidden2  not_hidden

Nun zum ursprünglichen Befehl:

$ find . -name ".*" -o -name "*" -exec echo Found {} \;
Found ./not_hidden

Es wird nur die nicht versteckte Datei gefunden.

Als Nächstes fügen wir Klammern hinzu, um die beiden Namenstests zusammenzufassen:

$ find . \( -name ".*" -o -name "*" \) -exec echo Found {} \;
Found .
Found ./not_hidden
Found ./.hidden1
Found ./.hidden2

Alle Dateien werden gefunden.

Die Lösung besteht darin, Klammern zu verwenden.

Mehr Details

Im Originalbefehl steht kein Operator zwischen -name "*"und -exec ... \;. Daher findwird der Standardoperator logisch-und verwendet. Da logisch-und enger bindet als logisch-oder ( -o), bedeutet dies, dass der Befehl wie folgt interpretiert wird:

find . \( -name ".*" \) -o \( -name "*" -exec echo Found {} \; \)

Dies bedeutet, dass execnur ausgeführt wird, wenn die erste nameBedingung nicht erfüllt ist.

Weitere Informationen finden Sie imBetreiberAbschnitt in man find.

Was passiert ohne-exec

Versuchen wir es mit einem einfachen -print:

$ find . -name ".*" -o -name "*" -print
./not_hidden

Wie Sie sehen, -printist die Bindung -name "*"mit dem impliziten logischen „Und“ wie oben beschrieben erfolgt.

Bedenken Sie jedoch, was passiert, wenn keine Aktion angegeben wird:

$ find . -name ".*" -o -name "*"
.
./not_hidden
./.hidden1
./.hidden2

Hier wurden alle Dateien gefunden. Der Grund dafür ist, dass in dieser Version -odienurOperator.

verwandte Informationen