¿Diferencia entre "xargs" y la sustitución de comandos?

14

En muchos casos, uso la sustitución de comandos en lugar de xargs. Por ejemplo rm $(ls)es lo mismo quels | xargs rm

¿Cuáles son realmente las diferencias entre ellos?

Creo que una de las diferencias es que la sustitución de comandos se ejecuta en subshell mientras se xargsejecuta en el shell actual, pero no estoy seguro.

Por favor enumere las diferencias.

Sinoosh
fuente

Respuestas:

9

Una diferencia es que cuando se usa la sustitución de comandos en lugar de una tubería, el tamaño de los datos pasados ​​está limitado por el tamaño del búfer de comandos, por lo que en algunos casos se trunca sin advertencia. Esto también significa que toda la salida del comando debe producirse y almacenarse en la memoria antes de pasar al siguiente comando, por lo que para salidas grandes puede usar mucha más memoria de la necesaria.

Otro problema con el primer método es que la salida se divide en espacios en blanco, por lo que no puede manejar nombres de archivos con espacios en ellos. xargstambién se ve afectado por el problema del espacio en blanco, pero se puede solucionar cambiando el delimitador utilizado. Por cierto, para manejar adecuadamente los nombres de archivo, necesitaría usar el byte nulo como delimitador en el segundo ejemplo.

Un tercer problema es que los globos se expanden, por lo que si un archivo tiene asteriscos o signos de interrogación en su nombre, habrá resultados inesperados.

Puede encontrar una buena discusión sobre el tema aquí: http://mywiki.wooledge.org/ParsingLs

La sintaxis correcta sería

echo rm *

o si debes usar xargs,

find . -maxdepth 1 -print0 | xargs -0 echo rm

Eliminar echocuando la salida se vea correcta.

user000001
fuente
1
@Sinoosh: xargstambién se ejecuta en un subshell debido a la tubería, a menos que habilite shopt -s lastpipe, en cuyo caso se ejecutará en el shell actual. Sin embargo, no creo que ejecutar un subshell sea un problema en este caso, ya que no está cambiando ninguna variable.
user000001
1
@Sinoosh: Para pasar los argumentos uno por uno, puede usar la -lbandera, como find . -maxdepth 1 -print0 | xargs -0 -l rm. Para la segunda pregunta, no se puede usar lscon xargs -0porque ls no divide la salida en el bute nulo, sino con líneas nuevas (que son válidas en los nombres de archivo BTW)
user000001
1
@Sinoosh: No es el primer párrafo, sino el segundo: xargs sin la -0opción sufre el problema del espacio en blanco.
user000001
1
Leer man xargs, usar echopara probar, no rm. xargsnos permite superar los límites de shell (algunos búferes están limitados a 65K, una lista de nombres de archivos no).
waltinator
1
@ Sinoosh: No tengo una buena referencia a mano, pero puede escribir xargs --show-limitsy verá el límite establecido en su sistema,
user000001