It has to do with the way Bash splits the argument. Now, never, ever put commands and there arguments in one variable. Use arrays instead (and also, stop using uppercase variable names, it's ugly and dangerous as it may clash with already defined variables). You should instead write:
myopts=( -e "ssh -p 1234" )
rsync "${myopts[@]}" 192.168.0.1:/a /a
In this case, rsync
will be launched with the following arguments:
-e
ssh -p 1234
192.168.0.1:/a
/a
which is probably what you want.
As to why it works this way: assume that
myopts='-e "ssh -p 1234"'
that is, myopts
is the following string:
-e "ssh -p 1234"
Unquoted, Bash will see four tokens. You can check it thus: in a terminal do:
$ myopts='-e "ssh -p 1234"'
$ printf 'Token: %s
' $myopts
Token: -e
Token: "ssh
Token: -p
Token: 1234"
so when you launch
rsync $myopts 192.168.0.1:/a /a
then it's like launching rsync
with these arguments:
-e
"ssh
-p
1234"
192.168.0.1:/a
/a
and you probably don't want that :)
Now, the variable $myopts
quoted, is just one token:
-e "ssh -p 1234"
so if you launch (observe the quotes):
rsync "$myopts" 192.168.0.1:/a /a
it's like launching rsync
with these arguments:
-e "ssh -p 1234"
192.168.0.1:/a
/a
and you don't want that either.
Really, the most robust way to solve this problem is to use Bash arrays. Look: define an array myopts
as (do it in a terminal):
$ myopts=( -e "ssh -p 1234" )
$ # myopts is an array with two arguments. Check this (observe the quotes):
$ printf "Argument: %s
" "${myopts[@]}"
Argument: -e
Argument ssh -p 1234
$ # Just for fun, what if we don't quote myopts?
$ printf "Argument: %s
" ${myopts[@]}
Argument: -e
Argument: "ssh
Argument: -p
Argument 1234"
So now, I guess that you understand why this:
rsync "${myopts[@]}" 192.168.0.1:/a /a
is like launching rsync
with these arguments:
-e
ssh -p 1234
192.168.0.1:/a
/a
… and that's probably what you want :)
.
Hope this helps!