What's the difference between $@ and $*
They aren't the same. $*
is a single string, whereas $@
is an actual array. To see the difference, execute the following script like so:
> ./test.sh one two "three four"
The script:
#!/bin/bash
echo "Using \"\$*\":"
for a in "$*"; do
echo $a;
done
echo -e "\nUsing \$*:"
for a in $*; do
echo $a;
done
echo -e "\nUsing \"\$@\":"
for a in "$@"; do
echo $a;
done
echo -e "\nUsing \$@:"
for a in $@; do
echo $a;
done
The explanation and the results for the four cases are below.
In the first case, the parameters are regarded as one long quoted string:
Using "$*":
one two three four
Case 2 (unquoted) - the string is broken into words by the for
loop:
Using $*:
one
two
three
four
Case 3 - it treats each element of $@ as a quoted string:
Using "$@":
one
two
three four
Last case - it treats each element as an unquoted string, so the last one is again split by what amounts to for three four
:
Using $@:
one
two
three
four
The difference comes in how they are expanded.
$*
expands to a single argument with all the elements delimited by spaces (actually the first character of $IFS
).
$@
expands to multiple arguments.
For example
#!/bin/bash
echo "With *:"
for arg in "$*"; do echo "<$arg>"; done
echo
echo "With @:"
for arg in "$@"; do echo "<$arg>"; done
$ /tmp/test.sh 1 2 "3 4"
With *:
<1 2 3 4>
With @:
<1>
<2>
<3 4>
You can review Bash Beginners Guide for more information. These to do pretty much the same thing with the difference of how it's separated:
$*
- 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.
$@
- Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word.
But unless you set IFS
to value other then default it could look identical.