xargs --replace / -I para argumentos individuales

10

Estoy tratando de usar xargs para ejecutar un comando para cada argumento proporcionado, pero desafortunadamente el indicador --replace / -I no parece funcionar correctamente cuando se conjuga con -n. Parece que {} se expandirá en la lista completa de argumentos leídos de stdin, independientemente de la opción -n.

Desafortunadamente, todos los ejemplos en la web parecen ser para comandos (mv, cp, rm) que tomarán múltiples argumentos donde se expande {}.

Por ejemplo, cuando se ejecuta:

echo a b c d | xargs -n 1 -I {} echo derp {}

El resultado es:

derp a b c d

Pero yo esperaba:

derp a
derp b
derp c
derp d

Sin embargo, ejecutarlo sin -I {} produce el resultado esperado:

echo a b c d | xargs -n 1 echo derp
derp a
derp b
derp c
derp d

¿Hay alguna manera de lograr esto con xargs? Mi intención última es usarlo para ejecutar múltiples sesiones ssh (paralelas), como

echo server{1..90} | xargs -n 1 -P 0 -I {} ssh {} 'echo $SOME_HOST_INFO'

Estoy corriendo xargs (GNU findutils) 4.4.2en RHEL 6.3.

André Fernandes
fuente
2
Curiosamente, funciona según lo previsto con BSD xargs, pero no con GNU xargs.
slhck
1
man xargson -I: Also, unquoted blanks do not terminate input items; instead the separator is the newline character. Implies -x and -L 1.entonces se comporta como está diseñado.
Daniel Beck
@ André, dado que tu intención es ejecutar Taks en paralelo, ¿has echado un vistazo a GNU en paralelo? Hace bien el trabajo. Descargo de responsabilidad: lo empaqueto para Debian.
rbrito
El paralelo GNU parecía un buen reemplazo, pero desafortunadamente no puedo instalarlo en este host en particular.
André Fernandes
@ AndréFernandes ¿Puede explicar si su razón no está cubierta por oletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html
Ole Tange

Respuestas:

5

Puede hacer eco con nuevas líneas para lograr el resultado esperado. En su caso con la expansión del servidor que sería:

$ echo -e server{1..4}"\n" | xargs -I{} echo derp {}
derp server1
derp server2
derp server3
derp server4
ahilsend
fuente
La idea de la nueva línea soluciona el problema (solo que no con su ejemplo exacto): echo server {1..4} | tr '' '\ n' | xargs -I {} echo derp {} servidor derp1 servidor derp2 servidor derp3 servidor derp4
André Fernandes
Lo siento, lo probé con zsh... Se arregló mi respuesta. echoNecesita la -eopción.
ahilsend
2

Puedes usar una tubería adicional como esta,

echo a b c d | xargs -n1 | xargs -I{} echo derp {}
derp a
derp b
derp c
derp d

El uso intermedio de xargs 'echos' cada letra 'abcd' individualmente debido a la opción '-n1'. Esto pone cada letra en su propia línea como esta,

echo a b c d | xargs -n1
a
b
c
d 

Es importante comprender que cuando se usa -I (reemplazo de cadena), xargs implica -L, que ejecuta el comando de utilidad (en su caso echo) una vez por línea. Además, no puede usar -n con -L ya que son mutuamente excluyentes.

sinergia77
fuente