I don't think I fully understand the nuances of quoting in bash.
I have a script, foo.sh
, which simply outputs numbered arguments.
#!/bin/bash
i=1
while [ $i -le $# ] ; do
v=$(eval "echo \$$i")
echo "$i: $v"
i=$((i + 1))
done
You can use it like so:
me@localhost] ./foo.sh a b c
1: a
2: b
3: c
If I set the variable args
to a value containing a space (like "super nintendo"
), I can use no-quoting to have bash treat it as two arguments:
me@localhost] args="super nintendo" ; ./foo.sh $args
1: super
2: nintendo
Or I can use weak-quoting (double quotes) to have bash treat it as a single argument, but expanding the variable to the actual value:
me@localhost] args="super nintendo" ; ./foo.sh "$args"
1: super nintendo
Or I can use strong-quoting (single quotes) to treat it literally as typed:
me@localhost] args="super nintendo" ; ./foo.sh '$args'
1: $args
However, weak quoting the special variable $@
seems to act as if there were no quoting. For example, bar.sh
below calls foo.sh
twice, once with weak quoting and once with no quoting.
#!/bin/bash
./foo.sh "$@"
./foo.sh $@
Calling this with ./bar.sh a b c
produces identical output for both calls to foo.sh
:
1: a
2: b
3: c
1: a
2: b
3: c
What I expected to see was the following:
1: a b c
1: a
2: b
3: c
What am I missing with quoting in bash here?
Best Answer
That's because
$@
is an array, and quoting of arrays has different rules:"${array[@]}"
or"$@"
expands to members of the array"${array[*]}"
or"$*"
expands to elements of the array joined by the first character from the$IFS
variable.Try it with several arguments, some of them containing spaces: