xargs --replace / -I pour les arguments simples

10

J'essaie d'utiliser xargs pour exécuter une commande pour chaque argument fourni, mais malheureusement, l'indicateur --replace / -I ne semble pas fonctionner correctement lorsqu'il est conjugué à -n. Il semble que {} se développera dans la liste complète des arguments lus depuis stdin, quelle que soit l'option -n.

Malheureusement, tous les exemples sur le Web semblent être pour des commandes (mv, cp, rm) qui prendront plusieurs arguments où {} est développé.

Par exemple, lors de l'exécution:

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

La sortie est:

derp a b c d

Mais je m'attendais à:

derp a
derp b
derp c
derp d

Cependant, l'exécuter sans -I {} donne le résultat attendu:

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

Existe-t-il un moyen d'y parvenir avec xargs? Mon intention ultime est de l'utiliser pour exécuter plusieurs sessions ssh (parallèles), comme

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

Je cours xargs (GNU findutils) 4.4.2sur RHEL 6.3.

André Fernandes
la source
2
Fait intéressant, cela fonctionne comme vous le souhaitez avec BSD xargs, mais pas GNU xargs.
slhck
1
man xargssur -I: Also, unquoted blanks do not terminate input items; instead the separator is the newline character. Implies -x and -L 1.Donc, il se comporte comme prévu.
Daniel Beck
@ André, puisque votre intention est de lancer taks en parallèle, avez-vous jeté un œil à GNU parallel? Il fait bien le travail. Avis de non-responsabilité: je le pack pour Debian.
rbrito
Le parallèle GNU semblait être un bon remplacement, mais malheureusement je ne peux pas l'installer sur cet hôte particulier.
André Fernandes
@ AndréFernandes Pouvez-vous élaborer si votre raison n'est pas couverte par oletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html
Ole Tange

Réponses:

5

Vous pouvez faire écho avec les nouvelles lignes pour atteindre le résultat attendu. Dans votre cas, avec l'extension du serveur, ce serait:

$ echo -e server{1..4}"\n" | xargs -I{} echo derp {}
derp server1
derp server2
derp server3
derp server4
ahilsend
la source
L'idée de la nouvelle ligne contourne le problème (mais pas avec votre exemple exact): serveur d'écho {1..4} | tr '' '\ n' | xargs -I {} echo derp {} derp server1 derp server2 derp server3 derp server4
André Fernandes
Désolé, testé avec zsh... Correction de ma réponse. echoa besoin de l' -eoption.
ahilsend
2

Vous pouvez utiliser un tuyau supplémentaire comme celui-ci,

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

L'utilisation intermédiaire de xargs 'echos' chaque lettre 'abcd' individuellement en raison de l'option '-n1'. Cela met chaque lettre sur sa propre ligne comme ça,

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

Il est important de comprendre lorsque vous utilisez -I (remplacement de chaîne), xargs implique -L, qui exécute la commande utilitaire (dans votre cas echo) une fois par ligne. De plus, vous ne pouvez pas utiliser -n avec -L car ils s'excluent mutuellement.

synergy77
la source