135

According to this page, $@ and $* do pretty much the same thing:

The $@ holds list of all arguments passed to the script. 
The $* holds list of all arguments passed to the script.

After searching all the top hits in google, I'm not able to find any explanation why there would be 2 seemingly duplicate syntaxes.

They appear to work the same in my scripts.

cat foo.sh
#!/bin/bash
echo The parameters passed in are $@
echo The parameters passed in are $*

./foo.sh herp derp
The parameters passed in are herp derp
The parameters passed in are herp derp
  1. Is one preferred over the other?
  2. Why are there 2 builtin variables to do the exact same thing?

Additional sources
bash.cyberciti.biz

Braiam
  • 35,380
  • 25
  • 108
  • 167
spuder
  • 17,643
  • 36
  • 91
  • 119
  • possible duplicate of [What is the difference between $\* and $@?](http://unix.stackexchange.com/questions/41571/what-is-the-difference-between-and). Also http://unix.stackexchange.com/questions/94126/should-i-use-or and http://unix.stackexchange.com/questions/9590/in-bash-what-is-the-safest-way-to-pass-variables-to-another-program-or – glenn jackman May 12 '14 at 16:21
  • Related: [What's the difference between $@ and $* in UNIX?](http://stackoverflow.com/questions/3307672/whats-the-difference-between-and-in-unix), [What is the difference between $@ and $* in shell scripts?](http://stackoverflow.com/questions/2761723/what-is-the-difference-between-and-in-shell-scripts), [What the difference between “$@” and “$*” in bash?](http://stackoverflow.com/questions/3008695/what-the-difference-between-and-in-bash). – manatwork May 12 '14 at 16:22
  • This does appear to be a duplicate. Strange that I couldn't find that other question when I searched for it. – spuder May 12 '14 at 16:27

4 Answers4

185

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
Ricardo
  • 111
  • 7
goldilocks
  • 86,451
  • 30
  • 200
  • 258
24

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>
phemmer
  • 70,657
  • 19
  • 188
  • 223
  • 3
    The OP want to know difference between `$*` and `$@`, not `"$*"` and `"$@"`. – cuonglm May 12 '14 at 16:26
  • `actually the first character of $IFS` i find that annotation really critical , as if you've recklessly defined IFS as a long string ,bash won't raise and error and would just use the first characters of the string (even if it was a space preceding the desired character) – polendina Dec 06 '21 at 11:18
11

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.

Karlson
  • 5,845
  • 32
  • 51
  • 1
    This is the best explanation imo, because it notes that they are the same, and only behave differently when *quoted*. – jmrah Jul 08 '20 at 23:38
6

Is one preferred over the other?

A short answer is "$@".

If you use them without double quote, they are the same. There is no one preferred over the other in this case. But I suggest you to always use them with double quote, except you know what exactly you want.

Why are there 2 builtin variables to do the exact same thing?

There are no difference between $* and $@, but "$@" and "$*" have.

You can see my answer in this post to see how are they different.

cuonglm
  • 150,973
  • 38
  • 327
  • 406