"$@"
expands to all of the command line arguments as separate words. It is different from "$*"
, which expands to all of the arguments as a single word.
"$@"
is especially useful for looping through arguments and handling arguments with spaces.
Consider we are in a script that we invoked with two arguments, like so:
$ ./script.sh "␣1␣2␣" "␣3␣␣4␣"
The variables $*
or $@
will expand into $1␣$2
, which in turn expand into 1␣2␣3␣4
so the loop below:
for var in $*; do # same for var in $@; do
echo \<"$var"\>
done
will print for both
<1>
<2>
<3>
<4>
While "$*"
will be expanded into "$1␣$2"
which will in turn expand into "␣1␣2␣␣␣3␣␣4␣"
and so the loop:
for var in "$*"; do
echo \<"$var"\>
done
will only invoke echo
once and will print
<␣1␣2␣␣␣3␣␣4␣>
And finally "$@"
will expand into "$1" "$2"
, which will expand into "␣1␣2␣" "␣3␣␣4␣"
and so the loop
for var in "$@"; do
echo \<"$var"\>
done
will print
<␣1␣2␣>
<␣3␣␣4␣>
thereby preserving both the internal spacing in the arguments and the arguments separation. Note that the construction for var in "$@"; do ...
is so common and idiomatic that it is the default for a for loop and can be shortened to for var; do ...
.