ejemplos xargs

ejemplos - xargs rm



Hacer que xargs ejecute el comando una vez para cada lĂ­nea de entrada (12)

El siguiente comando buscará todos los archivos (-type f) en /path y luego los copiará usando cp a la carpeta actual. Tenga en cuenta el uso de -I % para especificar un carácter de marcador de posición en la línea de comando cp para que los argumentos se puedan colocar después del nombre del archivo.

find /path -type f -print0 | xargs -0 -I % cp % .

Probado con xargs (GNU findutils) 4.4.0

¿Cómo puedo hacer que xargs ejecute el comando exactamente una vez por cada línea de entrada dada? Su comportamiento predeterminado es dividir las líneas y ejecutar el comando una vez, pasando varias líneas a cada instancia.

De http://en.wikipedia.org/wiki/Xargs :

buscar / ruta-tipo f -print0 | xargs -0 rm

En este ejemplo, find alimenta la entrada de xargs con una larga lista de nombres de archivos. xargs luego divide esta lista en listas y llama a rm una vez por cada lista. Esto es más eficiente que esta versión funcionalmente equivalente:

buscar / ruta de acceso -tipo f -exec rm ''{}'' /;

Sé que encontrar tiene la bandera "exec". Solo estoy citando un ejemplo ilustrativo de otro recurso.


En su ejemplo, el punto de canalizar la salida de find a xargs es que el comportamiento estándar de la opción -exec de find es ejecutar el comando una vez para cada archivo encontrado. Si está utilizando find y desea su comportamiento estándar, entonces la respuesta es simple: para empezar, no use xargs.


Estas dos formas también funcionan, y funcionarán para otros comandos que no usan find!

xargs -I ''{}'' rm ''{}'' xargs -i rm ''{}''

caso de uso de ejemplo:

find . -name "*.pyc" | xargs -i rm ''{}

eliminará todos los archivos pyc bajo este directorio, incluso si los archivos pyc contienen espacios.


Lo siguiente solo funcionará si no tiene espacios en su entrada:

xargs -L 1 xargs --max-lines=1 # synonym for the -L option

de la página del manual:

-L max-lines Use at most max-lines nonblank input lines per command line. Trailing blanks cause an input line to be logically continued on the next input line. Implies -x.


Me parece que todas las respuestas existentes en esta página son incorrectas, incluida la marcada como correcta. Eso se debe al hecho de que la pregunta está formulada de manera ambigua.

Resumen: si desea ejecutar el comando "exactamente una vez por cada línea de entrada", pasando la línea completa (sin la nueva línea) al comando como un solo argumento, entonces esta es la mejor manera compatible con UNIX de hacerlo:

... | tr ''/n'' ''/0'' | xargs -0 -n1 ...

GNU xargs puede o no tener extensiones útiles que le permiten eliminar tr , pero no están disponibles en OS X y otros sistemas UNIX.

Ahora por la larga explicación ...

Hay dos cuestiones a tener en cuenta al utilizar xargs:

  1. ¿Cómo se divide la entrada en "argumentos"; y
  2. Cuántos argumentos para pasar el comando hijo a la vez.

Para probar el comportamiento de xargs, necesitamos una utilidad que muestre cuántas veces se está ejecutando y con cuántos argumentos. No sé si hay una utilidad estándar para hacer eso, pero podemos codificarlo fácilmente en bash:

#!/bin/bash echo -n "-> "; for a in "$@"; do echo -n "/"$a/" "; done; echo

Suponiendo que lo guarde como se show en su directorio actual y lo haga ejecutable, aquí es cómo funciona:

$ ./show one two ''three and four'' -> "one" "two" "three and four"

Ahora, si la pregunta original es realmente sobre el punto 2. anterior (como creo que lo es, después de leerlo varias veces) y debe leerse así (cambios en negrita):

¿Cómo puedo hacer que xargs ejecute el comando exactamente una vez para cada argumento de entrada dado? Su comportamiento predeterminado es dividir la entrada en argumentos y ejecutar el comando tan pocas veces como sea posible , pasando múltiples argumentos a cada instancia.

entonces la respuesta es -n 1 .

Comparemos el comportamiento predeterminado de xargs, que divide la entrada alrededor del espacio en blanco y llama al comando tan pocas veces como sea posible:

$ echo one two ''three and four'' | xargs ./show -> "one" "two" "three" "and" "four"

y su comportamiento con -n 1 :

$ echo one two ''three and four'' | xargs -n 1 ./show -> "one" -> "two" -> "three" -> "and" -> "four"

Por otro lado, si la pregunta original era sobre el punto 1, se dividió la entrada y se leería así (muchas personas que vienen aquí parecen pensar que ese es el caso, o están confundiendo los dos problemas):

¿Cómo puedo hacer que xargs ejecute el comando con exactamente un argumento para cada línea de entrada dada? Su comportamiento predeterminado es dividir las líneas alrededor de los espacios en blanco .

Entonces la respuesta es más sutil.

Uno podría pensar que -L 1 podría ser de ayuda, pero resulta que no cambia el análisis de argumentos. Solo ejecuta el comando una vez para cada línea de entrada, con tantos argumentos como estaban allí en esa línea de entrada:

$ echo $''one/ntwo/nthree and four'' | xargs -L 1 ./show -> "one" -> "two" -> "three" "and" "four"

No solo eso, sino que si una línea termina con espacios en blanco, se anexa a la siguiente:

$ echo $''one /ntwo/nthree and four'' | xargs -L 1 ./show -> "one" "two" -> "three" "and" "four"

Claramente, -L no se trata de cambiar la forma en que xargs divide la entrada en argumentos.

El único argumento que lo hace de manera multiplataforma (excluyendo las extensiones GNU) es -0 , que divide la entrada en torno a los bytes NUL.

Entonces, solo es cuestión de traducir nuevas líneas a NUL con la ayuda de tr :

$ echo $''one /ntwo/nthree and four'' | tr ''/n'' ''/0'' | xargs -0 ./show -> "one " "two" "three and four"

Ahora el argumento de análisis parece correcto, incluido el espacio en blanco al final.

Finalmente, si combina esta técnica con -n 1 , obtendrá exactamente una ejecución de comando por línea de entrada, cualquiera sea la entrada que tenga, lo que puede ser otra forma de ver la pregunta original (posiblemente la más intuitiva, dado el título):

$ echo $''one /ntwo/nthree and four'' | tr ''/n'' ''/0'' | xargs -0 -n1 ./show -> "one " -> "two" -> "three and four"


No me gusta la respuesta -L porque no maneja archivos con espacios en ellos, lo cual es una función clave de find -print0 .

echo "file with space.txt" | xargs -L 1 ls ls: file: No such file or directory ls: space.txt: No such file or directory ls: with: No such file or directory

Una mejor solución es usar tr para convertir nuevas líneas a caracteres nulos ( /0 ) y luego usar el argumento xargs -0 .

echo "file with space.txt" | tr ''/n'' ''/0'' | xargs -0 ls file with space.txt

Otro problema con el uso de -L también es que no permite múltiples argumentos para cada llamada del comando xargs . Por ejemplo, la solución actualmente aceptada llamaría /bin/rm para cada una de las líneas, que es una tonelada de ejecutivos. Al usar el comando tr , entonces se puede usar -n para limitar el número de líneas leídas desde la entrada por cada invocación de la utilidad.

find . -name /*.java | tr ''/n'' ''/0'' | xargs -0 wc

Esto también le permite filtrar la salida de la búsqueda antes de convertir los saltos en nulos.

find . -name /*.xml | grep -v /workspace/ | tr ''/n'' ''/0'' | xargs -0 tar -cf xml.tar


Otra alternativa ...

find /path -type f | while read ln; do echo "processing $ln"; done


Parece que no tengo la reputación suficiente para agregar un comentario a la respuesta de Tobia anterior , así que estoy agregando esta "respuesta" para ayudar a aquellos de nosotros que deseen experimentar con xargs la misma manera en las plataformas Windows.

Aquí hay un archivo por lotes de Windows que hace lo mismo que el script "show" codificado rápidamente de Tobia:

@echo off REM REM cool trick of using "set" to echo without new line REM (from: http://www.psteiner.com/2012/05/windows-batch-echo-without-new-line.html) REM if "%~1" == "" ( exit /b ) <nul set /p=Args: "%~1" shift :start if not "%~1" == "" ( <nul set /p=, "%~1" shift goto start ) echo.


Puede limitar el número de líneas o los argumentos (si hay espacios entre cada argumento) utilizando las marcas --max-lines o --max-args, respectivamente.

-L max-lines Use at most max-lines nonblank input lines per command line. Trailing blanks cause an input line to be logically continued on the next input line. Implies -x. --max-lines[=max-lines], -l[max-lines] Synonym for the -L option. Unlike -L, the max-lines argument is optional. If max-args is not specified, it defaults to one. The -l option is deprecated since the POSIX standard specifies -L instead. --max-args=max-args, -n max-args Use at most max-args arguments per command line. Fewer than max-args arguments will be used if the size (see the -s option) is exceeded, unless the -x option is given, in which case xargs will exit.


Si desea ejecutar el comando para cada línea (es decir, el resultado) que proviene de find , entonces, ¿para qué necesita los xargs ?

Tratar:

find ruta -type f -exec su-comando {} /;

donde el literal {} se sustituye por el nombre del archivo y el literal /; Es necesario para find para saber que el comando personalizado termina allí.

EDITAR:

(después de la edición de su pregunta aclarando que usted sabe acerca de -exec )

Del man xargs :

-L max-lineas
Use en la mayoría de las líneas de entrada no en blanco de líneas máximas por línea de comando. Los espacios en blanco finales hacen que una línea de entrada continúe lógicamente en la siguiente línea de entrada. Implica -x.

Tenga en cuenta que los nombres de archivo que terminan con espacios en blanco podrían causarle problemas si utiliza xargs :

$ mkdir /tmp/bax; cd /tmp/bax $ touch a/ b c/ c $ find . -type f -print | xargs -L1 wc -l 0 ./c 0 ./c 0 total 0 ./b wc: ./a: No such file or directory

Entonces, si no te importa la opción -exec , es mejor que uses -print0 y -0 :

$ find . -type f -print0 | xargs -0L1 wc -l 0 ./c 0 ./c 0 ./b 0 ./a


ejecute ant task clean-all en todos los build.xml en la carpeta actual o en la subcarpeta.

find . -name ''build.xml'' -exec ant -f {} clean-all /;


find path -type f | xargs -L1 command

es todo lo que necesitas.