stringshellshposixparameter-expansion

Why does the shell expand a quoted "$@" as multiple parameters


The following command prints foo bar, as expected:

sh -c 'printf "$@"' -- "foo bar"

However, when called with foo and bar as separate arguments, it only prints foo:

sh -c 'printf "$@"' -- foo bar

(sh and bash have the same behavior here)

This indicates to me that the expression "$@" is turned into multiple parameters, leading to a call of printf foo bar, instead of printf "foo bar".

  1. Why is this the case? I thought that quotes denote a single string?
  2. How can i change the sh -c command to get the desired behaviour (printf "foo bar") when passing multiple arguments?

Solution

  • Why is this the case?

    Because $@ is special.

    I thought that quotes denote a single string?

    Not in the case of $@.

    How can i change the sh -c command to get the desired behaviour (printf "foo bar") when passing multiple arguments?

    You can use "$*" to join arguments with space (first character from IFS).

    From https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02 :

    2.5.2 Special Parameters

    @
    [...] When the expansion occurs within double-quotes [...] the initial fields shall be retained as separate fields [...]