¿Cuál es la diferencia entre “$ @” y “$ *” en Bash?

Me parece que ambos almacenan todos los argumentos de línea de comandos.

Entonces, ¿hay una diferencia entre los dos?

La diferencia es sutil; "$*" crea un argumento separado por la variable $IFS , mientras que "$@" se expandirá en argumentos separados. Como ejemplo, considere:

 for i in "$@"; do echo "@ '$i'"; done for i in "$*"; do echo "* '$i'"; done 

Cuando se ejecuta con múltiples argumentos:

 ./testvar foo bar baz 'long arg' @ 'foo' @ 'bar' @ 'baz' @ 'long arg' * 'foo bar baz long arg' 

Para más detalles:

http://www.gnu.org/software/bash/manual/bashref.html#Special-Parameters

ps

Se expande a los parámetros posicionales, comenzando desde uno. Cuando la expansión ocurre entre comillas dobles, se expande a una sola palabra con el valor de cada parámetro separado por el primer carácter de la variable especial IFS. Es decir, “$ *” es equivalente a “$ 1c $ 2c …”, donde c es el primer carácter del valor de la variable IFS. Si IFS no está configurado, los parámetros están separados por espacios. Si IFS es nulo, los parámetros se unen sin separadores intermedios.

ps

Se expande a los parámetros posicionales, comenzando desde uno. Cuando la expansión ocurre entre comillas dobles, cada parámetro se expande a una palabra separada. Es decir, “$ @” es equivalente a “$ 1” “$ 2” …. Si la expansión de comillas dobles ocurre dentro de una palabra, la expansión del primer parámetro se une con la parte inicial de la palabra original, y el la expansión del último parámetro se une con la última parte de la palabra original. Cuando no hay parámetros posicionales, “$ @” y $ @ se expanden a nada (es decir, se eliminan).

Una diferencia clave de mi POV es que "$@" conserva la cantidad original de argumentos. Es la única forma que lo hace.

Por ejemplo, si el archivo my_script contiene:

 #!/bin/bash main() { echo 'MAIN sees ' $# ' args' } main $* main $@ main "$*" main "$@" ### end ### 

y lo manejo así:

 my_script 'abc' de 

Obtendré esta salida:

 MAIN sees 5 args MAIN sees 5 args MAIN sees 1 args MAIN sees 3 args