Unterschied zwischen '{}' und {} im Befehl find?

18

In der Dokumentation sehe ich die Verwendung in beide Richtungen:

find . -type f -exec file '{}' \;

find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
Tarabyte
quelle
4
Sicher, es scheint nichts mit dem Befehl find zu tun zu haben und hat stattdessen damit zu tun, den aufgerufenen Befehl in Anführungszeichen zu setzen.
Zoredache
1
Probieren Sie es lieber mit Fisch als mit Bash.
Charles Duffy

Antworten:

24

Für die bashSchale '{}'und {}sind austauschbar. Dies ist nicht bei allen Shells (wie z. B. fish) der Fall .

Wenn Sie das Argument in einfache Anführungszeichen setzen, wird explizit angegeben, dass die geschweiften Klammern an gesendet werden sollen find. Abhängig von der Verwendung ersetzt die Bash-Shell manchmal den Inhalt von geschweiften Klammern.

Wie weiter unten zu sehen ist, ersetzt bash keine leeren Klammern und sie werden an den Befehl übergeben. Für den findBefehl spielt es keine Rolle.

$ echo {}
{}

$ echo {1}
{1}

$ echo {1,3}
1 3

$ echo '{1,3}'
{1,3}
Steven
quelle
4
Macht nichts mit Bash. Ist wichtig mit Fisch.
Charles Duffy
1
Ich würde ersetzen " are interchangeable"durch " are interchangeable in some shells, not in all of them. ALWAYS use the single quotes to make sure they get passed as-is to the find command"(gute Gewohnheiten beginnen, indem Sie sicherstellen, dass Sie den richtigen Weg verwenden, auch wenn Sie sich (immer?) Auf einem System befinden, das das Mehrdeutige zulässt)
Olivier Dulac
9

Bei fast allen verfügbaren Shell-Interpreten gibt es absolut keinen Unterschied zwischen '{}'und {}.

Die einfachen Anführungszeichen werden normalerweise verwendet, um die eingebettete Zeichenfolge davor zu schützen, durch etwas anderes ersetzt zu werden. Beispiel:

  • 'a b' ist ein einzelner Parameter mit drei Zeichen, ohne die Anführungszeichen, die zwei einzelne Zeichenparameter wären
  • '$b' a ist buchstäblich das Dollarzeichen, gefolgt vom Buchstaben b, ohne das Anführungszeichen, das in der Variablen b enthalten ist und möglicherweise nichts, wenn es nicht gesetzt ist
  • '!!' Wenn sie nicht in Anführungszeichen gesetzt sind und einige interaktive Shells enthalten, werden sie bis zum letzten Befehl im Verlauf erweitert
  • '*' Ist ein Wurfstern, wird er ohne Anführungszeichen durch die Liste der nicht ausgeblendeten Dateinamen im aktuellen Verzeichnis ersetzt.

Da weder der POSIX - Standard noch den Mainstream - Schalen ( sh(Bourne) ksh, bash, ash, dash, zsh, csh, tcsh) zu erweitern , {}um etwas anderes, sind die Anführungszeichen nicht erforderlich.

Es gibt jedoch eine exotische Shell mit dem Namen fish, die sich zufällig {}als leere Zeichenfolge ausdehnt , z.

> ps -p %self
  PID TTY          TIME CMD
 5247 pts/1    00:00:00 fish
> echo a {} b '{}'
a  b {}

Dies ist wahrscheinlich der Grund, warum die GNU- findDokumentation {}vor Interpretationen mit Anführungszeichen oder Backslashes schützt .

jlliagre
quelle
9

Für die meisten Benutzer (insbesondere für Benutzer von POSIX-Shells) besteht kein Unterschied.

Entsprechend dem Beispielabschnitt der Manpage für GNU find:

Beachten Sie, dass die geschweiften Klammern in einfache Anführungszeichen eingeschlossen sind, um sie vor der Interpretation als Shellskript-Interpunktion zu schützen.

Ich denke, die Autoren der GNU-Manpage irren sich vorsichtshalber, aber ich stelle fest, dass nicht alle Beispiele in ihrer Manpage die geschweiften Klammern zitieren. Diese Beispiele aus der offiziellen GNU-Find-Dokumentation lassen das Zitieren ebenfalls aus.

In den Beispielen aus der POSIX / Single UNIX-Spezifikation werden die Klammern bei Verwendung der Option nicht in Anführungszeichen gesetzt-exec .

Bei einer POSIX-Shell erfolgt die Parametererweiterung nur, wenn spezielle Parameter in geschweiften Klammern eingeschlossen sind - nicht jedoch bei leeren Klammern .

Die Bash-Shell enthält die Erweiterung von geschweiften Klammern als (nicht tragbares) Feature. Solche Muster werden jedoch nur dann erweitert, wenn ein Komma oder Punkte in den geschweiften Klammern enthalten sind . Bash verwendet auch Klammern für Befehl Gruppierung , aber dies nicht der Fall , es sei denn tatsächlich ist eine Gruppe von Befehlen innerhalb der Klammer.

Schließlich habe ich versucht , laufen find -exec ls -l {} \;in sh, dashund tcshdoch keines dieser Schalen der expandierte {}in irgendetwas anderes. Wie bereits erwähnt, wird die fishShell {}speziell behandelt , es handelt sich jedoch nicht um eine POSIX-Shell (die von ihren Erstellern und Benutzern als Vorteil angesehen wird). Es schadet nicht, die Klammern zu zitieren, aber faule Schreibkräfte, die die Fischschale nicht benutzen, sollten sich nicht schuldig fühlen, wenn sie sie weglassen.

Anthony G - Gerechtigkeit für Monica
quelle
sie irren sich nicht, sie versuchen sicherzustellen, dass die Leute den richtigen Weg verwenden (dh '{}'stattdessen verwenden {}), so dass ihre Shell {}an den find-Befehl sendet , ohne ihn zu interpretieren (wie oben von @ Charles-Duffy erwähnt, falls Sie zufällig Fische verwenden) , es wird interpretieren, {}aber nicht '{}', so dass Sie letzteres auf dieser Shell (und auf mehreren anderen!) verwenden müssen. Verwenden Sie daher immer, um '{}'zu vermeiden, von der Zweideutigkeit von{}
Olivier Dulac
6

Dies hängt von der Syntax Ihrer Shell ab. Wenn Sie Zweifel haben, wiederholen Sie es!

Führen Sie das aus

echo '{}'

und das.

echo {}

Wenn sie die gleiche Ausgabe erzeugen, lautet die Antwort für Ihre Shell "Ja". Wie andere angemerkt haben, wird es zumindest Ja in Bash und Nein in Fisch sein. Für die Ausgabe sollten Sie die Manpage eines bestimmten Befehls konsultieren.


Wenn Sie sich als nützlich erweisen möchten, können Sie sogar echoeine ganze Befehlszeile voranstellen , um den tatsächlichen Befehl mit all seinen Argumenten anzuzeigen, den Ihre Shell tatsächlich aufrufen würde. Beachten Sie jedoch, dass die Liste, die den Befehl und die Argumente enthält, ein echtes Array von Zeichenfolgen ist, von denen jede möglicherweise leer oder mit Leerzeichen versehen ist. Echo gibt sie jedoch mehrdeutig als durch Leerzeichen getrennte Liste aus.

Wie mit diesem etwas ausführlicheren Echo-Befehl (der Argumente in Anführungszeichen zeigt) überprüft werden kann,

#!/bin/sh
for a in "$@"; do
    printf '«%s» ' "$a"
done
echo ''

Geben Sie dies in die Befehlszeile ein,

find 'My Documents and Settings' -type f -exec file {} \;

bedeutet dies zu schlagen:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «{}» «;»

und das bei fisch:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «» «;»

Generell kann es nie schaden, etwas zu zitieren.

user2394284
quelle