Accessing bash command line args $@ vs $*

BashCommand Line-Arguments

Bash Problem Overview


In many SO questions and bash tutorials I see that I can access command line args in bash scripts in two ways:

$ ~ >cat testargs.sh 
#!/bin/bash

echo "you passed me" $*
echo "you passed me" $@

Which results in:

$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2

What is the difference between $* and $@?
When should one use the former and when shall one use the latter?

Bash Solutions


Solution 1 - Bash

The difference appears when the special parameters are quoted. Let me illustrate the differences:

$ set -- "arg  1" "arg  2" "arg  3"

$ for word in $*; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in $@; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in "$*"; do echo "$word"; done
arg  1 arg  2 arg  3

$ for word in "$@"; do echo "$word"; done
arg  1
arg  2
arg  3

one further example on the importance of quoting: note there are 2 spaces between "arg" and the number, but if I fail to quote $word:

$ for word in "$@"; do echo $word; done
arg 1
arg 2
arg 3

and in bash, "$@" is the "default" list to iterate over:

$ for word; do echo "$word"; done
arg  1
arg  2
arg  3

Solution 2 - Bash

A nice handy overview table from the Bash Hackers Wiki:

Syntax Effective result
$* $1 $2 $3 … ${N}
$@ $1 $2 $3 … ${N}
"$*" "$1c$2c$3c…c${N}"
"$@" "$1" "$2" "$3" … "${N}"

where c in the third row is the first character of $IFS, the Input Field Separator, a shell variable.

If the arguments are to be stored, load them in an array variable.

Solution 3 - Bash

$*

> Expands to the positional parameters, starting from one. When the > expansion occurs within double quotes, it expands to a single word > with the value of each parameter separated by the first character of > the IFS special variable. That is, "$*" is equivalent to "$1c$2c...", > where c is the first character of the value of the IFS variable. If > IFS is unset, the parameters are separated by spaces. If IFS is null, > the parameters are joined without intervening separators.

$@

> Expands to the positional parameters, starting from one. When the > expansion occurs within double quotes, each parameter expands to a > separate word. That is, "$@" is equivalent to "$1" "$2" ... If the > double-quoted expansion occurs within a word, the expansion of the > first parameter is joined with the beginning part of the original > word, and the expansion of the last parameter is joined with the last > part of the original word. When there are no positional parameters, > "$@" and $@ expand to nothing (i.e., they are removed).

Source: Bash man

Solution 4 - Bash

$@ is same as $*, but each parameter is a quoted string, that is, the parameters are passed on intact, without interpretation or expansion. This means, among other things, that each parameter in the argument list is seen as a separate word.

Of course, "$@" should be quoted.

http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST

Solution 5 - Bash

This example let may highlight the differ between "at" and "asterix" while we using them. I declared two arrays "fruits" and "vegetables"

fruits=(apple pear plumm peach melon)            
vegetables=(carrot tomato cucumber potatoe onion)

printf "Fruits:\t%s\n" "${fruits[*]}"            
printf "Fruits:\t%s\n" "${fruits[@]}"            
echo + --------------------------------------------- +      
printf "Vegetables:\t%s\n" "${vegetables[*]}"    
printf "Vegetables:\t%s\n" "${vegetables[@]}"    

See the following result the code above:

Fruits:	apple pear plumm peach melon
Fruits:	apple
Fruits:	pear
Fruits:	plumm
Fruits:	peach
Fruits:	melon
+ --------------------------------------------- +
Vegetables:	carrot tomato cucumber potatoe onion
Vegetables:	carrot
Vegetables:	tomato
Vegetables:	cucumber
Vegetables:	potatoe
Vegetables:	onion

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionoz123View Question on Stackoverflow
Solution 1 - Bashglenn jackmanView Answer on Stackoverflow
Solution 2 - BashSerge StroobandtView Answer on Stackoverflow
Solution 3 - BashMuffoView Answer on Stackoverflow
Solution 4 - BashrkosegiView Answer on Stackoverflow
Solution 5 - BashstefanssonView Answer on Stackoverflow