diferencia de opción xargs -I replace-str

16

Según tengo entendido, lo siguiente debería significar exactamente lo mismo:

ls -1 | xargs file {}
ls -1 | xargs -I{} file {}

si no se especifica la opción -I, el valor predeterminado es -I {}.

Quiero enumerar todos los archivos en el directorio actual y ejecutar el filecomando en cada uno de ellos. Algunos tienen espacios en sus nombres. Sin embargo, noté la diferencia. Vea abajo:

$ ls -1
Hello World
$ ls -1 | xargs file {}
{}:    ERROR: cannot open `{}' (No such file or directory)
Hello: ERROR: cannot open `Hello' (No such file or directory)
World: ERROR: cannot open `World' (No such file or directory)
$ ls -1 | xargs -I{} file {}
Hello World: directory

Con -I {} especificado explícitamente, los espacios en blanco en los nombres de archivo se tratan como se esperaba.

previsión
fuente
3
"si la opción -I no está especificada, el valor predeterminado es -I {}"; esto es incorrecto, al menos con GNU xargs.
jjlin
Entiendo mi error Debo especificar cualquiera xargs fileo xargs -I{} file {}. No debería ser xargs file {}. Supongo que al especificar explícitamente -I {}, el bash lo tratará como file "Hello World". Sin -I {}, se trata como file Hello World.
prospectightyj
1
(1) Esta discusión tiene poco que ver con el shell (bash). (2) Es bueno que conozca la -1opción ls, pero está activada de forma predeterminada cuando la salida de lses un archivo o una tubería, por lo que no la necesita aquí. (3) Estás confundiendo -Icon la opción obsoleta -i(minúscula I). -ifooes equivalente a -Ifoo, pero plain -ies equivalente a -I{}. Pero uso -I{}. (4) Si realmente quieres hacer lo que dices que quieres hacer, ¿por qué no decirlo file *?
Scott
@Scott Mi intención original era escribir `find. -nombre "* .mov" | xargs -I {} file {} `para encontrar todos los archivos mov de forma recursiva y ejecutarlos file. Pero se me ocurrió un ejemplo más simple usando ls. Tienes razón. Por eso, file *es lo mejor.
prospectightyj
1
encontrar tiene -exec.
Cristian Ciupitu

Respuestas:

20

El -Irequiere un marcador de posición definido. La -iopción asumirá {}es el marcador de posición. Aquí fue donde encontré cualquier suposición de {} man xargsal menos en Cygwin y CentOS.

xargs llamado sin ninguna de las opciones no necesita el marcador de posición y solo agrega el STDIN al final de los argumentos.

Simplemente agregue echoa sus ejemplos para ver qué está haciendo xargs:

$ ls -1
Hello World/

Su ejemplo de error usa {}:

$ ls -1 | xargs echo file {}
file {} Hello World/

entonces el filecmd ve argumentos {} Hello Worldy errores.

Si desea usar explícitamente {}en su llamada xargs:

$ ls -1 | xargs -i echo file {}
file Hello World/

O sin marcador de posición:

$ ls -1 | xargs echo file
file Hello World/

xargs como se llamó anteriormente no necesita el {}. Agrega el STDIN al final del comando sin un marcador de posición. El uso de {} generalmente significa que desea que se ejecute el STDIN en algún lugar en el medio del cmd, como en:

$ ls -1 | xargs -i mv {} /path/to/someplace/.
johnnyB
fuente
Eso está muy claro. Aunque su respuesta llega un poco tarde, leerla realmente refuerza mi comprensión.
prospectightyj