Uso de llaves entrelazadas {} como argumentos para los comandos y sus opciones

11

Ejemplos

Recientemente he encontrado ejemplos del uso de pares de llaves {}, sin nada entre las llaves de apertura y cierre, como argumentos para los comandos e incluso para sus opciones:

cat foo | xargs -I{} echo {}

find . -size 0 -exec rm -i {} \;

Sin documentación

Mi problema es que no puedo encontrar una documentación en el Manual de GNU Bash que describa el uso {}en el contexto de los ejemplos anteriores.

No creo que sea una expansión de parámetros , porque un signo de dólar debe preceder a las llaves en una expansión de parámetros como en ${}.

Tampoco puede ser una expansión de llaves, porque toma la forma de {x..y[..incr]}, donde xy yno son opcionales.

Tampoco puede ser una agrupación de comandos , porque {}se usa como argumentos.

Preguntas

  1. ¿Qué {}significa incluso un par de llaves encerradas , en general, como argumento para cualquier comando que lo acepte?

  2. ¿Dónde puedo encontrar una documentación que describa el uso de {}como argumentos?

Niko Gambt
fuente
Algunos comandos tienen estas opciones {}, lo targetsque significa actuar, con el findcomando, es eliminar / rmencontrar archivos.
Tuyen Pham el

Respuestas:

16

Estas llaves se dejan solas por bash; pertenecen findy xargs, respectivamente, y se describen en sus páginas de manual.

man find

-exec mando ;

Ejecutar comando ; verdadero si se devuelve el estado 0. Todos los siguientes argumentos para buscar se consideran argumentos del comando hasta que se encuentre un argumento consistente en ;. La cadena {}se reemplaza por el nombre del archivo actual que se procesa en todas partes donde aparece en los argumentos del comando, no solo en los argumentos donde está solo, como en algunas versiones de find. Es posible que sea necesario escapar de estas dos construcciones (con a \) o citarlas para protegerlas de la expansión del shell. Consulte la sección EJEMPLOS para ver ejemplos del uso de la -execopción. El comando especificado se ejecuta una vez para cada archivo coincidente. El comando se ejecuta en el directorio de inicio. Hay problemas de seguridad inevitables en torno al uso de la -exec acción; deberías usar la -execdiropción en su lugar.

-exec mando {} +

Esta variante de la -execacción ejecuta el comando especificado en los archivos seleccionados, pero la línea de comando se crea agregando cada nombre de archivo seleccionado al final; El número total de invocaciones del comando será mucho menor que el número de archivos coincidentes. La línea de comando se construye de la misma manera que xargsconstruye sus líneas de comando. Solo {}se permite una instancia de dentro del comando. El comando se ejecuta en el directorio de inicio. Si findencuentra un error, esto a veces puede causar una salida inmediata, por lo que algunos comandos pendientes pueden no ejecutarse en absoluto. Esta variante de -execsiempre devuelve verdadero.

-execdir mando ;

-execdir mando {} +

Me gusta -exec, pero el comando especificado se ejecuta desde el subdirectorio que contiene el archivo coincidente, que normalmente no es el directorio en el que comenzó a buscar. Este es un método mucho más seguro para invocar comandos, ya que evita las condiciones de carrera durante la resolución de las rutas a los archivos coincidentes. Al igual que con la -exec acción, la + forma de -execdir creará una línea de comando para procesar más de un archivo coincidente, pero cualquier invocación de comando solo enumerará los archivos que existen en el mismo subdirectorio. Si usa esta opción, debe asegurarse de que su $PATHvariable de entorno no haga referencia.; de lo contrario, un atacante puede ejecutar cualquier comando que desee dejando un archivo con el nombre apropiado en un directorio en el que ejecutará -execdir. Lo mismo se aplica a tener entradas en las $PATHque están vacías o que no son nombres de directorio absolutos. Si findencuentra un error, esto a veces puede causar una salida inmediata, por lo que algunos comandos pendientes pueden no ejecutarse en absoluto. El resultado de la acción depende de si se está utilizando la +o la ;variante; -execdir el comando {} + siempre devuelve verdadero, mientras que el -execdir comando {} ; devuelve verdadero solo si el comando devuelve 0.

man xargs

-I replace-str

Reemplace las ocurrencias de replace-str en los argumentos iniciales con nombres leídos de la entrada estándar. Además, los espacios en blanco sin comillas no terminan los elementos de entrada; en cambio, el separador es el carácter de nueva línea. Implica -xy -L 1.

-i[ replace-str ], --replace[ =replace-str ]

Esta opción es sinónimo de -Ireplace-str si se especifica replace-str . Si falta el argumento replace-str , el efecto es el mismo que -I{}. Esta opción está en desuso; utilizar -Ien su lugar.

Editar: y aquí POR QUÉ bash ignora esas llaves:

man bash

{ lista; }

La lista simplemente se ejecuta en el entorno de shell actual. La lista debe terminarse con una nueva línea o punto y coma. Esto se conoce como un comando de grupo. El estado de retorno es el estado de salida de la lista. Tenga en cuenta que, a diferencia de los metacaracteres ( y ) , { y } son palabras reservadas y deben aparecer donde se permite reconocer una palabra reservada. Como no causan un salto de palabra, deben estar separados de la lista por espacios en blanco u otro metacarácter de shell.

Para enfatizar: la lista debe terminarse con una nueva línea o punto y coma .

tink
fuente
1
¡Gracias! Me molesta que quien escribió man xargsni siquiera se molestó en explicar lo que {}realmente significa, ni el autor redirigió (sin juego de palabras) al lector a la explicación -execen la página de manual de find.
Niko Gambt
@NikoGambt - Simpatizo ...
tink
55
@NikoGambt Bueno, {} realmente no significa nada para xargs, excepto por ser el valor predeterminado para -i, que está en desuso. No estoy seguro de qué explicación es necesaria más allá de eso. En el ejemplo que publicaste, bien podría haber sido xargs -Iab echo ab; Es una elección puramente arbitraria.
Random832
@ Random832 Después de probar un poco más -I, ahora entiendo qué hace realmente esa opción. Sí, {}es arbitrario, como dijiste. Estaba confundido por la explicación If the replace-str argument is missing, the effect is the same as -I{}. Si -Isin argumento fuera el mismo que -I{}, cat foo | xargs -I echo {}produciría el mismo resultado que ejecutar cat foo | xargs -I{} echo {}. Sin embargo, no son lo mismo. El primero es un error, y lo que me confundió aún más fue el mensaje de error xargs: {}: No such file or directory, pero eso se debe solo a la implementación.
Niko Gambt
1
@NikoGambt -I(mayúscula I) no se puede ejecutar sin un argumento. El argumento para -Ifue echo. Esta es la principal diferencia entre -Iy -i(y la razón -i está en desuso, ya que las opciones con argumentos no obligatorios son poco comunes y confusas)
Random832