Ich wollte rekursiv chmod go+w
in 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 find
wird 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 exec
nur ausgeführt wird, wenn die erste name
Bedingung 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, -print
ist 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 -o
dienurOperator.