Why isn't passed quoted $@
a single argument?
f2()
{
echo "f2: $1"
}
f1()
{
local x=("$@")
f2 "${x[@]}"
}
f1 x y
Invocation:
$ bash t537.sh
f2: x
Here I expect that x y
is printed because ${x[@]}
is passed to f2
in quoted form.
Why passing quoted ${x[@]}
passes "x" "y"
rather than passing "x y"
?
P.S. It seems that "$*"
may be the solution here. However, I'm trying to understand why "${x[@]}"
does not work here.
"$@"
is a special magical thingy, which makes an exception to the general rule. And for very good reasons. (the same applies to"${array[@]}"
by extension) – ilkkachu Jan 23 '24 at 13:50"$@"
is very much more often the right thing to do, as it keeps together arguments that contains separators (spaces, tabs). for exemple if you have 3 files:file1
file2 with spaces
file3
and write a script that asks the filenames as arguments, the 2nd should be entered with quotes"file2 with spaces"
and these should stay together. The"$@"
would allow you to do that, whereas"$*"
or$*
or$@
would not. Other use case : https://mywiki.wooledge.org/BashPitfalls#for_arg_in_.24.2A – Olivier Dulac Jan 23 '24 at 15:01x=$@
orx="$@"
, you'd get the args (positional parameters) joined to a single string. But the details vary between the shells, so better use$*
there if joining them is what you want. – ilkkachu Jan 23 '24 at 15:34("$@")
I convert command line arguments into an array, 2) I've fixed my code viaecho "f2: $@"
. – pmor Jan 24 '24 at 09:52echo
joins its args with spaces. But that's a feature of echo, and e.g. printf would be different there. if you have the argsfoo
andbar
, thenecho "f2: $@"
will run echo with the two argsf2: foo
andbar
. Whileecho "f2: $*"
would pass just the single argf2: foo bar
(assuming the defaultIFS
) – ilkkachu Jan 24 '24 at 10:22printf "f2: %s\n" "$@"
andprintf "f2: %s\n" "$*"
produce very different results. – Stephen Kitt Jan 24 '24 at 10:33