Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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"

Whats the difference between these scripts? Why the first one replaces $@ with the first argument only?

share|improve this question
add comment

2 Answers

up vote 13 down vote accepted

$@ 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=$@.

share|improve this answer
    
+1, great explanation –  1_CR Oct 26 '12 at 19:56
    
+1. This will also work: zenity --text="$*" -- "$*" expands to a single word. –  glenn jackman Oct 26 '12 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 '12 at 9:59
add comment

$@ 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
share|improve this answer
    
Please shed light on why the $text variant from the OP's question works as expected –  1_CR Oct 26 '12 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 '12 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 '12 at 19:48
    
@jw013: But according to the Bash Reference Manual, "$@" does undergo word splitting, even in variable assignments. –  ruakh Oct 27 '12 at 1:35
    
@ruakh The bash manual doesn't say that as far as I know. Do you have a quote? –  jw013 Oct 27 '12 at 1:37
show 4 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.