81 votes

xargs avec plusieurs arguments

J'ai une entrée source, input.txt

a.txt
b.txt
c.txt

Je veux introduire ces données dans un programme comme le suivant :

my-program --file=a.txt --file=b.txt --file=c.txt

J'essaie donc d'utiliser xargs mais sans succès.

cat input.txt | xargs -i echo "my-program --file"{}

Il donne

my-program --file=a.txt
my-program --file=b.txt
my-program --file=c.txt

Mais je veux

my-program --file=a.txt --file=b.txt --file=c.txt

Une idée ?

160voto

sauliux Points 1321

Ne les écoutez pas tous. :) Regardez cet exemple :

echo argument1 argument2 argument3 | xargs -l bash -c 'echo this is first:$0 second:$1 third:$2'

La sortie sera :

this is first:argument1 second:argument2 third:argument3

27 votes

Ha. "Ne les écoutez pas tous" me fait rire.

19 votes

Si vous essayez de faire cela sous OSX, utilisez -L1, par exemple. echo argument1 argument2 argument3 | xargs -L1 bash -c 'echo this is first:$0 second:$1 third:$2' | xargs

3 votes

Mais je pense que cette réponse est incorrecte. Le fichier a 3 lignes mais dans cette réponse il y a 3 arguments dans une ligne !

39voto

Ole Tange Points 700

Aucune des solutions données jusqu'à présent ne traite correctement les noms de fichiers contenant des espaces. Certaines échouent même si les noms de fichiers contiennent ' ou ". Si vos fichiers d'entrée sont générés par des utilisateurs, vous devez vous préparer à des noms de fichiers surprenants.

GNU Parallel traite joliment ces noms de fichiers et vous donne (au moins) 3 solutions différentes. Si votre programme prend 3 et seulement 3 arguments, cela fonctionnera :

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo a2.txt; echo b2.txt; echo c2.txt;) |
parallel -N 3 my-program --file={1} --file={2} --file={3}

Ou :

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo a2.txt; echo b2.txt; echo c2.txt;) |
parallel -X -N 3 my-program --file={}

Si, toutefois, votre programme prend autant d'arguments qu'il peut en contenir sur la ligne de commande :

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo d1.txt; echo e1.txt; echo f1.txt;) |
parallel -X my-program --file={}

Regardez la vidéo d'introduction pour en savoir plus : http://www.youtube.com/watch?v=OpaiGYxkSuQ

22voto

yabt Points 191

Pourquoi pas :

echo $'a.txt\nb.txt\nc.txt' | xargs -n 3 sh -c '
   echo my-program --file="$1" --file="$2" --file="$3"
' argv0

9voto

jjo Points 863

C'est plus simple si vous utilisez deux invocations xargs : la première pour transformer chaque ligne en --file=... 2. pour faire réellement le truc de xargs ->.

$ cat input.txt | xargs -I@ echo --file=@ | xargs echo my-program
my-program --file=a.txt --file=b.txt --file=c.txt

7voto

Bart Sas Points 1137

Vous pouvez utiliser sed au préfixe --file= à chaque ligne et ensuite appeler xargs :

sed -e 's/^/--file=/' input.txt | xargs my-program

1 votes

Après avoir cherché sur Google (quatre ans plus tard), j'ai trouvé ma propre solution (similaire)... spécifiquement, pour cette question, ce serait plutôt : echo a.txt b.txt c.txt | xargs | sed 's/ / --file=/g' | xargs echo my-program --file Ma solution compliquée consistait plutôt à faire passer des noms de fichiers (comme les journaux d'Apache) dans une longue ligne de commande. Par exemple : ls /var/log/apache2/*access.log | xargs | sed 's/ / -f /g' | xargs echo myprogram -f

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X