10

When I run the following script with some arguments like arg1 arg2 arg3:

#!/bin/bash
zenity --entry --text="$@"

zenity creates an entry dialog with this text: "arg1" whereas I expect "arg1 arg2 arg3"

If I use a variable like the following script it shows all arguments for the entry text.

#!/bin/bash
text="$@"
zenity --entry --text="$text"

What's the difference between these scripts? Why does the first one replace $@ with the first argument only?

2 Answers 2

16

$@ expands to separate words (whereas $* expands to a single word), as explained in the bash manual. Thus, when you write

zenity --text="$@"

it expands to

zenity --text="$1" "$2" "$3"

However, shell variable assignments do not undergo word splitting. Note that field / word splitting is omitted in the list of expansions for variable assignments in the bash manual. This behavior is consistent with the POSIX spec. So, when you write

text="$@"

the variable text gets all of the positional parameters as a single word, equivalent to if you had written text="$*". Indeed, this is the reason double quotes are often unnecessary in variable assignments. Both

text=$@

and

text=$*

are perfectly safe.

So,

text=$@
zenity --option="$text"

expands "$text" to a single word, which is why this works. Note that the --option="$@" is just a normal argument to the command zenity, and not a shell variable assignment, which is why word splitting takes place here but not in text=$@.

2
  • 1
    +1. This will also work: zenity --text="$*" -- "$*" expands to a single word. Oct 26, 2012 at 20:31
  • +1 for teaching me one thing: man != documentation. I should had searched info bash, it also contains the manual section you linked to.
    – manatwork
    Oct 27, 2012 at 9:59
7

$@ get expanded each parameter in separate word, becoming

zenity --entry --text="arg1" "arg2" "arg3" # syntactically wrong for zenity

Use $* instead to expand it in a single word

zenity --entry --text="$*"

which will become

zenity --entry --text="arg1 arg2 arg3" # syntactically correct for zenity
9
  • Please shed light on why the $text variant from the OP's question works as expected
    – iruvar
    Oct 26, 2012 at 18:11
  • @ChandraRavoori, you caught me with that. According to the manual “Word splitting is not performed, with the exception of "$@"” and “If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word.”, so I would expect text="$@" to be expanded to text="arg1" "arg2" "arg3", which should fail. But certainly is not the case.
    – manatwork
    Oct 26, 2012 at 18:37
  • @ChandraRavoori The reason is field splitting doesn't happen in variable assignments. I explain in more detail in my answer.
    – jw013
    Oct 26, 2012 at 19:48
  • @jw013: But according to the Bash Reference Manual, "$@" does undergo word splitting, even in variable assignments.
    – ruakh
    Oct 27, 2012 at 1:35
  • @ruakh The bash manual doesn't say that as far as I know. Do you have a quote?
    – jw013
    Oct 27, 2012 at 1:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .