There is no difference if you do not put $*
or $@
in quotes. But if you put them inside quotes (which you should, as a general good practice), then $@
will pass your parameters as separate parameters, whereas $*
will just pass all params as a single parameter.
Take these scripts (foo.sh
and bar.sh
) for testing:
>> cat bar.sh
echo "Arg 1: $1"
echo "Arg 2: $2"
echo "Arg 3: $3"
echo
>> cat foo.sh
echo '$* without quotes:'
./bar.sh $*
echo '$@ without quotes:'
./bar.sh $@
echo '$* with quotes:'
./bar.sh "$*"
echo '$@ with quotes:'
./bar.sh "$@"
Now this example should make everything clear:
>> ./foo.sh arg1 "arg21 arg22" arg3
$* without quotes:
Arg 1: arg1
Arg 2: arg21
Arg 3: arg22
$@ without quotes:
Arg 1: arg1
Arg 2: arg21
Arg 3: arg22
$* with quotes:
Arg 1: arg1 arg21 arg22 arg3
Arg 2:
Arg 3:
$@ with quotes:
Arg 1: arg1
Arg 2: arg21 arg22
Arg 3: arg3
Clearly, "$@"
gives the behaviour that we generally want.
More detailed description:
Case 1: No quotes around $*
and $@
:
Both have same behaviour.
./bar.sh $*
=> bar.sh
gets arg1
, arg2
and arg3
as separate arguments
./bar.sh $@
=> bar.sh
gets arg1
, arg2
and arg3
as separate arguments
Case 2: You use quotes around $*
and $@
:
./bar.sh "$*"
=> bar.sh
gets arg1 arg2 arg3
as a single argument
./bar.sh "$@"
=> bar.sh
gets arg1
, arg2
and arg3
as a separate arguments
More importantly, $*
also ignores quotes in your argument list. For example, if you had supplied ./foo.sh arg1 "arg2 arg3"
, even then:
./bar.sh "$*"
=> bar.sh
will still receive arg2
and arg3
as separate parameters!
./bar.sh "$@"
=> will pass arg2 arg3
as a single parameter (which is what you usually want).
Notice again that this difference occurs only if you put $*
and $@
in quotes. Otherwise they have the same behaviour.
Official documentation: http://www.gnu.org/software/bash/manual/bash.html#Special-Parameters