¿Cómo puedo hacer que xargs ejecute el comando exactamente una vez para 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 sublistas y llama a rm una vez por cada sublista. Esto es más eficiente que esta versión funcionalmente equivalente:
find / path -type f -exec rm '{}' \;
Sé que find tiene la bandera "exec". Solo estoy citando un ejemplo ilustrativo de otro recurso.
find /path -type f -delete
sería aún más eficiente :)Respuestas:
Lo siguiente solo funcionará si no tiene espacios en su entrada:
de la página del manual:
fuente
xargs -n 1
como el que usted mostró "lista de argumentos demasiado larga".MAX-LINES
se omite, el valor predeterminado es 1, por lo tantoxargs -l
es suficiente. Verinfo xargs
.echo "foo bar" | xargs -n1 echo
. por lo tanto, si canaliza cosas como 'ls', no manejará bien los espacios.-L 1
no responde la pregunta original, y lo-n 1
hace solo en una de las posibles interpretaciones. Vea mi larga respuesta a continuación.-L 1
hace. Para mí, el OP parecía estar claramente tratando de evitar el comportamiento de fragmentación predeterminado, y dado que esto fue aceptado, supongo que tenía razón. Su respuesta aborda un caso de uso ligeramente diferente en el que también desea el comportamiento de fragmentación.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 para cada línea de entrada dada", pasando toda la línea (sin la nueva línea) al comando como un argumento único, entonces esta es la mejor manera compatible con UNIX para hacerlo:
GNU
xargs
puede o no tener extensiones útiles que le permitan eliminartr
, pero no están disponibles en OS X y otros sistemas UNIX.Ahora para la larga explicación ...
Hay dos problemas a tener en cuenta al usar xargs:
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 codificarla con bastante facilidad en bash:
Suponiendo que lo guarde como
show
en su directorio actual y lo haga ejecutable, así es como funciona:Ahora, si la pregunta original es realmente sobre el punto 2 anterior (como creo que es, después de leerlo varias veces) y debe leerse así (cambia en negrita):
entonces la respuesta es
-n 1
.Comparemos el comportamiento predeterminado de xargs, que divide la entrada en espacios en blanco y llama al comando las menos veces posible:
y su comportamiento con
-n 1
:Si, por otro lado, la pregunta original era sobre el punto 1. división de entrada y debía leerse así (muchas personas que vienen aquí parecen pensar que ese es el caso, o están confundiendo los dos problemas):
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 había en esa línea de entrada:No solo eso, sino que si una línea termina con espacios en blanco, se agrega a la siguiente:
Claramente,
-L
no se trata de cambiar la forma en que xargs divide la entrada en argumentos.El único argumento que lo hace de una manera multiplataforma (excluyendo las extensiones GNU) es
-0
, que divide la entrada alrededor de bytes NUL.Entonces, solo es cuestión de traducir nuevas líneas a NUL con la ayuda de
tr
:Ahora el análisis del argumento se ve bien, 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 que sea la entrada que tenga, que puede ser otra forma de ver la pregunta original (posiblemente la más intuitiva, dado el título):fuente
-L
ejecuta el comando una vez por línea de entrada (pero un espacio al final de una línea lo une a la siguiente línea, y la línea aún se divide en argumentos según el espacio en blanco); while-n
ejecuta el comando una vez por argumento de entrada. Si cuenta el número de->
en los ejemplos de salida, ese es el número de veces que./show
se ejecuta el script .xargs
puede o no tener extensiones útiles que le permitan eliminarlo.tr
Tiene una extensión muy útil; fromxargs --help
- -d, --delimiter = CHARACTER Los elementos en la secuencia de entrada están separados por CHARACTER, no por espacios en blanco; desactiva el procesamiento de cotizaciones y barras invertidas y el procesamiento lógico de EOF-L
.-L
no dice cuántas veces ejecutar el script por línea, dice cuántas líneas de datos de entrada consumir a la vez.Si desea ejecutar el comando para cada línea (es decir, resultado)
find
, ¿para qué necesita el comandoxargs
?Tratar:
find
ruta de-type f -exec
su comando{} \;
donde el literal
{}
se sustituye por el nombre del archivo y\;
se necesita el literal parafind
saber que el comando personalizado termina allí.EDITAR:
(después de la edición de su pregunta aclarando que sabe
-exec
)De
man xargs
:Tenga en cuenta que los nombres de archivo que terminan en blanco podrían causarle problemas si usa
xargs
:Entonces, si no te importa la
-exec
opción, mejor usa-print0
y-0
:fuente
-L 1
es la solución simple pero no funciona si alguno de los archivos contiene espacios en ellos. Esta es una función clave del-print0
argumento find : separar los argumentos por el carácter '\ 0' en lugar de espacios en blanco. Aquí hay un ejemplo:Una mejor solución es usar
tr
para convertir nuevas líneas en caracteres nulos (\0
), y luego usar elxargs -0
argumento. Aquí hay un ejemplo:Si luego necesita limitar el número de llamadas, puede usar el
-n 1
argumento para hacer una llamada al programa para cada entrada:Esto también le permite filtrar la salida de find antes de convertir los saltos en nulos.
fuente
-L
también es que no permite múltiples argumentos para cadaxargs
llamada de comando"?Otra alternativa ...
fuente
Estas dos formas también funcionan, y funcionarán para otros comandos que no usan find!
ejemplo de uso:
eliminará todos los archivos pyc de este directorio, incluso si los archivos pyc contienen espacios.
fuente
es todo lo que necesitas.
fuente
El siguiente comando encontrará todos los archivos (-tipo f)
/path
y luego los copiarácp
a la carpeta actual. Tenga en cuenta el uso de if-I %
para especificar un carácter de marcador de posición en lacp
línea de comando 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
fuente
Puede limitar el número de líneas o argumentos (si hay espacios entre cada argumento) usando las banderas --max-lines o --max-args, respectivamente.
fuente
Parece que no tengo suficiente reputación para agregar un comentario a la respuesta anterior de Tobia, por lo que estoy agregando esta "respuesta" para ayudar a aquellos de nosotros que quieran experimentar de
xargs
la misma manera en las plataformas de Windows.Aquí hay un archivo por lotes de Windows que hace lo mismo que el script "show" rápidamente codificado de Tobia:
fuente
Las respuestas de @Draemon parecen estar bien con "-0" incluso con espacio en el archivo.
Estaba probando el comando xargs y descubrí que "-0" funciona perfectamente con "-L". incluso los espacios son tratados (si la entrada fue nula terminada). Lo siguiente es un ejemplo :
Lo siguiente dividirá los valores nulos y ejecutará el comando en cada argumento de la lista:
entonces
-L1
ejecutará el argumento en cada carácter terminado en nulo si se usa con "-0". Para ver la diferencia intente:incluso esto se ejecutará una vez:
El comando se ejecutará una vez ya que "-L" ahora no se divide en byte nulo. debe proporcionar "-0" y "-L" para que funcione.
fuente
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: no use xargs para empezar.
fuente
find
, y es por eso que no prefieren la-exec
opción.ejecute ant task clean-all en cada build.xml en la carpeta actual o subcarpeta.
fuente
ant
instalado.