eval $SSH_CMD $SSH_USER@$SSH_DST "mkdir $dir1 && mv $dir1 $dir2 && touch $dir2"
This is practically the same as running
eval "$SSH_CMD $SSH_USER@$SSH_DST mkdir $dir1 && mv $dir1 $dir2 && touch $dir2"
eval
joins the arguments it gets to a single string, and then runs that as shell command. In particular, the &&
acts on the local side, so the shell runs first ssh ... mkdir dir1
, and if that succeeds, it runs mv dir1 dir2
, etc. mkdir
runs on the remote host, but mv
on the local host, where dir1
doesn't exist.
There's no need to use eval
here. Your first command would do without it:
$SSH_CMD $SSH_USER@$SSH_DST "mkdir $dir1 && mv $dir1 $dir2 && touch $dir2"
When $SSH_CMD
is not quoted, it gets split to the three words ssh
, -i
, and path_to/identity
just as you want. This works, but is somewhat unclean, and you'd get into trouble if you had to include arguments with whitespace within $SSH_CMD
, or used glob characters there.
If you need to store a variable number of command arguments, like in SSH_CMD
, it's better to use an array. Also, quote the other variables to prevent word splitting, too:
ssh_cmd=(ssh -i path_to/identity)
ssh_user=user
ssh_host=server
dir1=dir1
dir2=dir2
"${ssh_cmd[@]}" "$ssh_user@$ssh_host" "mkdir $dir1 && mv $dir1 $dir2 && touch $dir2"
See BashFAQ 050: I'm trying to put a command in a variable, but the complex cases always fail! and How can we run a command stored in a variable? for more details.
$PATH
variable is for, so you can specify the "ssh" command you want to use. Or are you saying that on system1, it's called "ssh" and on system2 it has a different name like "secure_shell"? – glenn jackman Feb 21 '19 at 18:20ssh
but some executable that actually takes the same or similar syntax... – atapaka Feb 21 '19 at 18:22SSH_CMD
contains options too, and relies on the shell to do the word-splitting and filename globbing without messing it up. – Kusalananda Feb 21 '19 at 18:33