0

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.

pmor
  • 599
  • 2
    In short: Because "$@" 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
  • I was about to post what @ikkachy already commented. But I'd add: in the general case, using "$@" 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:01
  • Note that, I don't see it explicitly mentioned in the linked post, but if you did x=$@ or x="$@", 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
  • @ilkkachu Thanks. FYI: 1) By doing ("$@") I convert command line arguments into an array, 2) I've fixed my code via echo "f2: $@". – pmor Jan 24 '24 at 09:52
  • 1
    @pmor, yes, that works too since echo joins its args with spaces. But that's a feature of echo, and e.g. printf would be different there. if you have the args foo and bar, then echo "f2: $@" will run echo with the two args f2: foo and bar. While echo "f2: $*" would pass just the single arg f2: foo bar (assuming the default IFS) – ilkkachu Jan 24 '24 at 10:22
  • 1
    So for example, printf "f2: %s\n" "$@" and printf "f2: %s\n" "$*" produce very different results. – Stephen Kitt Jan 24 '24 at 10:33

0 Answers0