147

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

3

4 Answers 4

198

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
2
  • 3
    Why make such subtle design? Commented Sep 20, 2021 at 8:30
  • I agree, it's a hacked, non-intuitive design predating Bash, the idea that "$@" should expand to multiple words. Some other syntax was needed. And that other syntax should have worked not only with $*, but also with $anyOtherVariable. Probably, unquoted $@ should have been words, and ${@otherVariable} should have worked similarly. Decades too late now! Commented Nov 1, 2023 at 21:26
27

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>
2
  • 3
    The OP want to know difference between $* and $@, not "$*" and "$@". Commented May 12, 2014 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) Commented Dec 6, 2021 at 11:18
13

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.

1
  • 1
    This is the best explanation imo, because it notes that they are the same, and only behave differently when quoted. Commented Jul 8, 2020 at 23:38
7

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.