¿Qué significa `(backquote / backtick) en los comandos?

160

Me encontré con el siguiente comando:

sudo chown `id -u` /somedir

y me pregunto: ¿cuál es el significado del `símbolo? Noté, por ejemplo, que si bien el comando anterior funciona bien, el siguiente no:

sudo chown 'id -u' /somedir
gws
fuente

Respuestas:

201

Esto es un retroceso . Un backtick no es un signo de cita. Tiene un significado muy especial. El shell evalúa (ejecuta) todo lo que escribe entre backticks antes del comando principal (como chownen sus ejemplos), y ese comando usa el resultado de esa ejecución, como si escribiera ese resultado en ese lugar en el línea de comando.

Y qué

sudo chown `id -u` /somedir

se ejecuta efectivamente (según su ID de usuario )

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

Eche un vistazo a esta pregunta para saber por qué, en muchas situaciones, no es una buena idea usar backticks.

Por cierto, si alguna vez quisiste usar una barra de retroceso literalmente, por ejemplo , en una cadena, puedes escapar colocando una barra invertida ( \) antes.

rozcietrzewiacz
fuente
36
Esto explica los backticks bastante bien, pero usar $(your expression)es una mejor manera de hacer lo mismo, ya $()que le permite anidar expresiones. por ejemplo: lo cd $(dirname $(type -P touch))colocará en el directorio que contiene el touchcomando
Khaja Minhajuddin
11
@KhajaMinhajuddin Definitivamente tienes razón acerca de anidar: la pregunta mencionada anteriormente lo cubre en detalle. Pero aunque creo que es una buena práctica usarlo $()en la mayoría de las situaciones, no hace que los backticks sean peores . Para fines prácticos, hay que admitir que son mucho más rápidos de escribir en la línea de comando (2 pulsaciones de teclas en comparación con al menos 5, incluidas Shift).
rozcietrzewiacz
2
@rozcietrzewiacz Su último comentario probablemente sea cierto para la mayoría de los teclados, pero $( )definitivamente es más fácil de escribir que ` `al menos en un teclado francés.
jlliagre
1
@KhajaMinhajuddin Puede anidar backticks, pero necesita escapar del segundo nivel de backticks, y en el segundo nivel de anidación necesita 3 backticks, 3er nivel de anidación 5 backticks, 4to nivel 7, y c.
JustinCB
66

Me gustaría agregar algunos puntos más aquí.

El backtick en `…`realidad se llama sustitución de comando . El propósito de la sustitución de comandos es evaluar el comando que se coloca dentro del backtick y proporcionar su resultado como argumento para el comando real.

La sustitución de comandos se puede hacer de dos maneras se está utilizando $(…)y el otro es `…`. Ambos funcionan igual, pero la $(…)forma es la forma moderna y tiene más claridad y legibilidad.

Y entonces

sudo chown $(id -u) /somedir

Se puede preferir sobre el otro.

Y una cosa más que debe tener en cuenta aquí es la relación de sustitución de comandos con las reglas de citas bash como se menciona en el documento bash .

Si la sustitución aparece entre comillas dobles, la división de palabras y la expansión de nombre de archivo no se realizan en los resultados.

Kannan Mohan
fuente
8
Además, $(...)anida mejor.
Kusalananda
$()y "``"no funcionan de la misma manera
Kun
10

Una nota de aclaración rara vez se cubre:

Los backticks (a veces también llamados Graves porque también funciona como acento común en francés y otros idiomas) sustituyen solo la Salida estándar , pero no el Error estándar.

Entonces para continuar con el ejemplo anterior:

file `which hostname`

funcionará como se esperaba, pero en:

file `which hostnameX`

whichdevolverá un error, y esa salida irá al error estándar, en lugar de sustituir en la línea de comando al lado de file; no habrá salida estándar, que puede confirmar ejecutando:

which hostnameX

which hostnameX 2>/dev/null

En este caso,

file `which hostnameX` 

producirá dos mensajes de error (el primero, debido which hostnameXy el segundo justo después del primero, debido al archivo en sí, que encuentra que falta el nombre del archivo y, por lo tanto, todo el comando

esencialmente se reducirá a solo:

file

que, por supuesto, es un mal uso y devolverá un error de uso.

(si desea verificarlo usted mismo, puede probar:

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
fuente
4

La tecla de retroceso `ejecuta el contenido de la cadena incluida, así que algo como esto

file `which hostname`

encontrará la ruta al comando hostname y luego le dirá cómo se creó.

El comando que ingresó en su pregunta se ejecuta id -upara obtener la identificación de usuario efectiva y luego cambia la propiedad de / somedir a ese usuario.

Julian
fuente
2

Este símbolo significa que cualquier cosa dentro de él se interpreta como el resultado de ese comando.

por ejemplo:

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

Lo anterior hace que el threedirectorio se copie en mi /homedirectorio.

Hanan N.
fuente
1

Los backticks se asemejan a la sustitución de comandos. Esta sintaxis acentos abiertos es arcaico, y saber el signo de dólar con dos paréntesis es común: $().

¿Qué es la sustitución de comandos?

La sustitución de comandos es una operación única con sintaxis dedicada tanto para ejecutar un comando como para tener su salida almacenada en una variable para su uso posterior.

Un ejemplo con fecha:

thedate=$(date)

Entonces podríamos imprimir el resultado: 'La fecha es% s \ n' "$ thedate" `.

  1. La sintaxis de sustitución de comando es $().
  2. El comando en sí es date.
  3. Combinando ambos obtenemos $(date)cuál es su salida la sustitución.
  4. Mostramos el valor de salida retenido por la variable con printf, según el comando anterior.
usuario9303970
fuente