Was bedeutet `(backquote / backtick) in Befehlen?

159

Ich bin auf folgenden Befehl gestoßen:

sudo chown `id -u` /somedir

und ich frage mich: was bedeutet das `symbol? Mir ist zum Beispiel aufgefallen, dass der obige Befehl zwar gut funktioniert, der folgende Befehl jedoch nicht:

sudo chown 'id -u' /somedir
gws
quelle

Antworten:

201

Dies ist ein Backtick . Ein Backtick ist kein Anführungszeichen. Es hat eine ganz besondere Bedeutung. Alles, was Sie zwischen Backticks eingeben, wird von der Shell vor dem Hauptbefehl ausgewertet (ausgeführt) (wie chownin Ihren Beispielen), und die Ausgabe dieser Ausführung wird von diesem Befehl verwendet, so als würden Sie diese Ausgabe an dieser Stelle in das Feld eingeben Befehlszeile.

Na und

sudo chown `id -u` /somedir

effektiv läuft (abhängig von Ihrer Benutzer-ID ) ist:

sudo chown 1000 /somedir
  \    \     \     \
   \    \     \     `-- the second argument to "chown" (target directory)
    \    \     `-- your user ID, which is the output of "id -u" command
     \    `-- "chown" command (change ownership of file/directory)
      `-- the "run as root" command; everything after this is run with root privileges

Schauen Sie sich diese Frage an, um zu erfahren, warum es in vielen Situationen keine gute Idee ist, Backticks zu verwenden.

Übrigens, wenn Sie einen Backtick jemals wörtlich verwenden wollten, z. B. in einem String, können Sie ihn umgehen, indem Sie einen Backslash ( \) davor setzen.

rozcietrzewiacz
quelle
36
Dies erklärt Backticks ziemlich gut, aber mit können Sie $(your expression)das Gleiche tun $(), um Ausdrücke zu verschachteln. Zum Beispiel: cd $(dirname $(type -P touch))CD Sie in das Verzeichnis mit dem touchBefehl
Khaja Minhajuddin
11
@KhajaMinhajuddin Sie haben definitiv Recht mit dem Schachteln - die oben genannte Frage befasst sich ausführlich damit. Aber auch wenn ich denke, dass es $()in den meisten Situationen eine gute Praxis ist , werden Backticks dadurch nicht schlechter . Aus praktischen Gründen muss man zugeben, dass sie in der Befehlszeile viel schneller zu tippen sind (2 Tastenanschläge im Vergleich zu mindestens 5 einschließlich Shift).
Rozcietrzewiacz
2
@rozcietrzewiacz Ihre letzte Bemerkung trifft wahrscheinlich auf die meisten Tastaturen zu, $( )ist aber definitiv einfacher zu tippen als ` `zumindest auf einer französischen Tastatur.
Juli
1
@KhajaMinhajuddin Sie können Backticks verschachteln, aber Sie müssen der 2. Ebene der Backticks entkommen, und 2. Ebene der Verschachtelung benötigen Sie 3 Backticks, 3. Ebene der Verschachtelung 5 Backticks, 4. Ebene 7, und c.
JustinCB
66

Ich möchte hier noch einige Punkte hinzufügen.

Das Backtick `…`wird eigentlich als Befehlsersetzung bezeichnet . Der Zweck der Befehlssubstitution besteht darin, den Befehl zu bewerten, der sich innerhalb des Backtick befindet, und sein Ergebnis als Argument für den tatsächlichen Befehl bereitzustellen.

Die Befehlsersetzung kann auf zwei Arten erfolgen: die eine $(…)und die andere `…`. Beide funktionieren gleich, aber die $(…)Form ist die moderne Art und Weise und hat mehr Klarheit und Lesbarkeit.

Und so

sudo chown $(id -u) /somedir

kann gegenüber dem anderen bevorzugt werden.

Und eine weitere Sache, die Sie hier beachten müssen, ist die Befehlsersetzungsbeziehung mit den Bash-Zitierregeln, wie im Bash- Dokument erwähnt .

Wenn die Ersetzung in doppelten Anführungszeichen steht, werden Wortteilung und Dateinamenerweiterung für die Ergebnisse nicht ausgeführt.

Kannan Mohan
quelle
8
Auch $(...)Nester besser.
Kusalananda
$()und "``"nicht auf die gleiche Weise arbeiten
Kun
10

Ein Hinweis zur Klarstellung wird selten behandelt:

Backticks (manchmal auch als Graves bezeichnet, da sie in Französisch und anderen Sprachen häufig als Akzent verwendet werden) ersetzen nur die Standardausgabe , nicht jedoch den Standardfehler.

So fahren Sie mit dem vorherigen Beispiel fort:

file `which hostname`

wird wie erwartet funktionieren, aber in:

file `which hostnameX`

whichGibt einen Fehler zurück, und diese Ausgabe wird auf Standardfehler gesetzt, anstatt in die Befehlszeile neben zu ersetzen file. Es wird überhaupt keine Standardausgabe geben, die Sie durch Ausführen von bestätigen können:

which hostnameX

which hostnameX 2>/dev/null

In diesem Fall,

file `which hostnameX` 

Es werden zwei Fehlermeldungen ausgegeben (die erste aufgrund which hostnameXund die zweite unmittelbar nach der ersten aufgrund der Datei selbst, die feststellt, dass der Dateiname fehlt, und somit der gesamte Befehl

wird im Wesentlichen auf nur reduzieren:

file

Dies ist natürlich eine falsche Verwendung und gibt einen Verwendungsfehler zurück.

(Wenn Sie es selbst überprüfen möchten, können Sie versuchen:

file `which hostnameX 2>/dev/null`    # just the file-command bad-usage error msg is printed

file `which hostnameX 2>/dev/null` 2>/dev/null  # now nothing is printed on the screen :)
Dave K
quelle
4

Das Backtick `führt den Inhalt des beiliegenden Strings aus, also ungefähr so

file `which hostname`

Hier finden Sie den Pfad zum Befehl hostname und erfahren, wie er erstellt wurde.

Der Befehl, den Sie in Ihre Frage id -ueingeben, wird ausgeführt, um die effektive Benutzer-ID abzurufen, und ändert dann den Besitz von / somedir in diesen Benutzer.

julianisch
quelle
2

Dieses Symbol bedeutet, dass alles, was sich darin befindet, als Ergebnis dieses Befehls interpretiert wird.

zum Beispiel:

$ls /home
one two
$pwd
/usr/three
$cp `pwd` /home
$ls /home
one two three

Das obige führt dazu, dass das threeVerzeichnis in mein /homeVerzeichnis kopiert wird .

Hanan N.
quelle
1

Die Backticks ähneln der Befehlsersetzung. Diese Syntax ist archaisch Backticks, und weiß das Dollarzeichen mit zwei Klammern sind gemeinsam: $().

Was ist eine Befehlsersetzung?

Die Befehlsersetzung ist eine einzelne Operation mit dedizierter Syntax, mit der sowohl ein Befehl ausgeführt als auch seine Ausgabe zur späteren Verwendung in einer Variablen gespeichert werden kann.

Ein Beispiel mit Datum:

thedate=$(date)

Wir könnten dann das Ergebnis ausgeben: 'Das Datum ist% s \ n' "$ thedate" `.

  1. Die Befehlssubstitutionssyntax lautet $().
  2. Der Befehl selbst ist date.
  3. Wenn wir beides kombinieren, erhalten wir, $(date)welche Ausgabe die Substitution ist.
  4. Wir zeigen den von der Variablen gehaltenen Ausgabewert mit printfdem obigen Befehl an.
user9303970
quelle