All the answers here are about command line encoding.
There's no way around it. And bash have very complete solutions. If you want to get really advanced, there's the hacks included for pasting, but those are arcane even for gnu bash devs.
The most obvious solution is to not quote, and just escape what your shell would consider the end of the argument to ssh
. So that everything after the command is treated as the parameter, which is the command string passed to your remote shell.
The only thing the quotes are doing in your example are masking the end of the command and the terminations, such as ;
and &
. And all the answers are about masking the end of line too, but with lots of overhead.
You will understand it when you realize
ssh -tq myuser@hostname "sudo -u scriptuser bash -c \"ls -al\""
Is exactly the same as
ssh -tq myuser@hostname sudo -u scriptuser bash -c "ls -al"
as far as your shell is concerned.
so to run you complex command, just escape the command line terminators:
ssh user@host [[ -d "/tmp/Some directory" ]] \&\& rm -rf "/tmp/Some directory"
or
ssh user@host set +xe\; export PATH=~/bin\; [ -e /etc/somefile ] \&\& echo ok \|\| echo missing\; echo "this ends the example of 'complex command'. bye $USER."\; echo \$HOSTNAME;
The above line will execute everything remotely. all up to the last non-escaped ;
in the very last character, as that ends the ssh
command line. All the rest is a string passed as argument.
Note that one $
is escaped, while another is not. This gives you control if you want the variable substitution to happen on the local host (before sending the command) or on the remote host. In the example above, $USER
will be replaced before sending the command, so it holds the name of the user running ssh
on the local host, while \$HOSTNAME
is escape, so it will be substituted on the remote host, and show that hostname. All the catch-all solutions on other answers don't give you this control and mostly behave as if you were using single quotes all the time around your argument.