¿Por qué xargs omite el primer argumento al pasar a subshell?

8

Buscando una manera de invocar más de un comando en una línea única de xargs, encontré la recomendación en findutils para invocar el shell de xargs de esta manera:

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

Lo curioso es que si uso xargs así, por alguna razón se salta el primer argumento:

$ 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

¿Hay algún problema con mi versión de shell o xargs? ¿Esa documentación es inexacta?

Uso de xargs (GNU findutils) 4.4.2 y GNU bash, versión 4.3.11 (1) -release .

elias
fuente

Respuestas:

13

La página del -c stringcomando man [bash] dice: " Si la opción -c está presente, los comandos se leen de la cadena. Si hay argumentos después de la cadena, se asignan a los parámetros posicionales, comenzando con $ 0 " . - La clave es $ 0 ; significa que el nombre del comando será el primer argumento.

seq 10 | xargs sh -c 'echo $@; echo $0' sh
1 2 3 4 5 6 7 8 9 10
sh
Janis
fuente
¡Oh ya veo! ¡así que por eso los documentos lo ponen moveal final en el ejemplo! Debería haber leído más detenidamente ... ¡Gracias! =)
elias
11

¿Por qué xargs omite el primer argumento al pasar a subshell?

No lo hace. Bash asigna el primer argumento a $ 0:

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

$@se expande a $1 $2 $3... En consecuencia, el valor de $0no está incluido en $@.

John1024
fuente
Esta explicación es mucho más clara que la de @ Janis, pero la respuesta de Janis incluye una buena solución al problema.
alexis