What is the difference between $@ and $* in shell scripts?

In shell scripts, what is the difference between $@ and $*?

Which one is the preferred way to get the script arguments?

Are there differences between the different shell interpreters about this?


From here:

$@ behaves like $* except that when quoted the arguments are broken up properly if there are spaces in them.

Take this script for example (taken from the linked answer):

for var in "$@"
do
    echo "$var"
done

Gives this:

$ sh test.sh 1 2 '3 4'
1
2
3 4

Now change "$@" to $*:

for var in $*
do
    echo "$var"
done

And you get this:

$ sh test.sh 1 2 '3 4'
1
2
3
4

(Answer found by using Google)


A key difference from my POV is that "$@" preserves the original number of arguments. It's the only form that does. For that reason it is very handy for passing args around with the script.

For example, if file my_script contains:

#!/bin/bash

main()
{
   echo 'MAIN sees ' $# ' args'
}

main $*
main $@

main "$*"
main "$@"

### end ###

and I run it like this:

my_script 'a b c' d e

I will get this output:

MAIN sees 5 args

MAIN sees 5 args

MAIN sees 1 args

MAIN sees 3 args