Pourquoi xargs ignore-t-il le premier argument lors du passage en sous-shell?

8

À la recherche d'un moyen d'invoquer plusieurs commandes dans une ligne unique xargs, j'ai trouvé la recommandation dans findutils pour invoquer le shell à partir de xargs comme ceci:

$ find ... | xargs sh -c 'command $@'

Ce qui est drôle, c'est que si j'utilise des xargs comme ça, pour une raison quelconque, cela saute le premier argument:

$ seq 10 | xargs bash -c 'echo $@'
2 3 4 5 6 7 8 9 10
$ seq 10 | xargs -n2 bash -c 'echo $@'
2
4
6
8
10

Quelque chose ne va pas avec ma version shell ou xargs? Cette documentation est-elle inexacte?

Utilisation de xargs (GNU findutils) 4.4.2 et GNU bash, version 4.3.11 (1) -release .

elias
la source

Réponses:

13

La page de manuel [bash] indique: " -c stringSi l'option -c est présente, les commandes sont lues à partir de la chaîne. S'il y a des arguments après la chaîne, ils sont affectés aux paramètres positionnels, en commençant par $ 0. " - La clé est $ 0 ; cela signifie que le nom de la commande doit être le premier argument.

seq 10 | xargs sh -c 'echo $@; echo $0' sh
1 2 3 4 5 6 7 8 9 10
sh
Janis
la source
Oh je vois! c'est pourquoi les docs mettent ça moveà la fin dans l'exemple! J'aurais dû lire plus attentivement ... Merci! =)
elias
11

Pourquoi xargs ignore-t-il le premier argument lors du passage en sous-shell?

Ce n'est pas le cas. Bash assigne le premier argument à $ 0:

$ seq 10 | xargs -n2 bash -c 'echo $0'
1
3
5
7
9

$@s'étend à $1 $2 $3.... Par conséquent, la valeur de $0n'est pas incluse dans $@.

John1024
la source
Cette explication est beaucoup plus claire que celle de @ Janis, mais la réponse de Janis comprend une bonne solution au problème.
alexis