Der Ärger mit dem ursprünglichen Versuch:
find www/*.html -type f -exec sh -c "echo $(basename {})" \;
ist, dass der Code $(basename {})
einmal ausgeführt wird, bevor der Befehl find
Exec ist utet. Die Ausgabe der einzelnen basename
ist {}
, da dies der Basisname {}
als Dateiname ist. So ist der Befehl, der von Fund ausgeführt ist:
sh -c "echo {}"
für jede Datei gefunden, aber find
ersetzt eigentlich die ursprünglichen (unveränderte) Dateinamen jedes Mal, weil die {}
Zeichen in der Zeichenfolge erscheinen ausgeführt werden.
Wenn Sie es wollen, arbeiten Sie einfache Anführungszeichen statt doppelte Anführungszeichen verwenden:
find www/*.html -type f -exec sh -c 'echo $(basename {})' \;
jedoch machen echo
Wiederholung auf die Standardausgabe, was basename
ohnehin auf die Standardausgabe geschrieben hätte ein wenig sinnlos:
find www/*.html -type f -exec sh -c 'basename {}' \;
und wir können das noch weiter senken, natürlich, zu:
find www/*.html -type f -exec basename {} \;
Können Sie hier auch den Unterschied zwischen einfachen und doppelten Anführungszeichen erklären?
Dies ist Routine Shell-Verhalten. Nehmen wir einen etwas anderen Befehl (aber nur leicht - die Namen der Dateien könnten sich irgendwo unter dem Verzeichnis www
befinden, nicht nur eine Ebene tiefer), und schauen Sie sich die Single-Quote (SQ) - und Double-Quote (DQ) -Versionen an der Befehl:
find www -name '*.html' -type f -exec sh -c "echo $(basename {})" \; # DQ
find www -name '*.html' -type f -exec sh -c 'echo $(basename {})' \; # SQ
Die einfachen Anführungszeichen übergeben das Material, das direkt dem Befehl beigefügt wird.Somit wird die Schale in der SQ-Befehlszeile, die find
startet entfernt die umschließenden Anführungszeichen und der find
Befehl sieht seine $9
Argument wie:
echo $(basename {})
, da die Shell die Anführungszeichen entfernt. Zum Vergleich: Das Material in den Anführungszeichen wird von der Shell verarbeitet. So wird in der DQ-Befehlszeile, die Schale (das startet find
- nicht das startete man vonfind
) sieht den $(basename {})
Teil der Zeichenfolge und führt es aus, zurück {}
bekommen, so dass die Saite übergibt sie an find
als $9
Argument ist:
echo {}
Nun, wenn find
seine tut -exec
Aktion, in beiden Fällen ist es die {}
durch den Dateinamen ersetzt, die es (zum Zwecke der Beweisführung, www/pics/index.html
) nur gefunden. So erhalten Sie zwei verschiedene Befehle ausgeführt werden:
sh -c 'echo $(basename www/pics/index.html)' # SQ
sh -c "echo www/pics/index.html" # DQ
Es gibt eine (leichte) Notations Betrüger dort passiert - das sind die entsprechenden Befehle, die Sie an der Shell-Typ würde. Die $2
der Shell, die gestartet wird, enthält in beiden Fällen keine Anführungszeichen - die gestartete Shell sieht keine Anführungszeichen.
Wie Sie sehen können, gibt der DQ-Befehl einfach den Dateinamen wieder; Der Befehl SQ führt den Befehl basename
aus, erfasst seine Ausgabe und gibt dann die erfasste Ausgabe wieder. Ein wenig reduktionistisches Denken zeigt, dass der DQ-Befehl als -print
anstelle von -exec
geschrieben werden könnte, und der SQ-Befehl könnte als -exec basename {} \;
geschrieben werden.
Wenn Sie GNU verwenden find
, es unterstützt die -printf
Aktion, die von Format Directives so verfolgt werden kann, dass basename
läuft nicht notwendig ist. Dies ist jedoch nur in GNU find
verfügbar; Der Rest der Diskussion gilt für jede Version von find
, auf die Sie wahrscheinlich treffen werden.
Dies ist eine großartige Antwort und Erklärung.Könnten Sie auch den Unterschied zwischen einfachen Anführungszeichen und Anführungszeichen hier erklären? –
Vielen Dank für das Hinzufügen der Sachen über die Zitate –
Es gibt offensichtlich keinen Grund, 'sh -c' hier zu verwenden, aber' -exec sh -c 'echo "$ (Basisname" {} ")"' \; "sollte immer noch Anführungszeichen enthalten, um das Teilen von Wörtern zu verhindern. in diesem Fall wäre '-exec sh -c 'echo" $ (Basisname "$ 1") "' sh {} \;' wirklich vorzuziehen. – BroSlow