Now the && is not within quotes, again. Also, the semicolon and the pipe later on are not within quotes, either. That said, your quoting is a little confused. It doesn't have to be so chaotic.
Keep in mind that the string after the ssh command will be interpreted twice. Once on the local machine, once on the remote machine. So let's start from the top without quotes:
Code:
ssh -f ${host_list[0]} cd $address && nohup Rscript ${program[0]}.R > ${program[0]}_sh.txt ; echo The job ${program[0]} is finished | mutt zwang10@mtu.edu -s ${program[0]} is finished;
so, we actually want to pass three arguments to ssh:
-f, the hostname, and the code to execute on the remote host -- there's really no reason for the command to be split into multiple arguments.
Now,
-f is a literal, no need to quote it.
The hostname is a variable, and while in this particular case it doesn't contain spaces, it's always a good idea to quote your variables. Single quotes would prevent expansion of the variable which we do not want, so it's definitely double quotes for this one, as you correctly used in your examples.
Last, our command contains variables which we want expanded on the local host (because that's where they are defined -- if the variables were defined on the remote host, you would want single quotes to have them expand there), so why don't we put the entire command within double quotes to keep the local shell from splitting it into multiple arguments and interpretting the semicolons, &&'s, pipes, etc:
Code:
ssh -f "${host_list[0]}" "cd $address && nohup Rscript ${program[0]}.R > ${program[0]}_sh.txt ; echo The job ${program[0]} is finished | mutt zwang10@mtu.edu -s ${program[0]} is finished;"
What will happen now? the local shell will split the line into four tokens,
ssh,
-f,
${host_list[0]}, and the command. It will remove the double quotes and also expand all variables that are
not within single quotes. So, the command sent to the remote shell is:
Code:
cd /home/campus27/zwang10/Desktop/AWRR/program/power/vmodel_1/nprot/K_10 && nohup Rscript L_1.R > L_1_sh.txt ; echo The job L_1 is finished | mutt zwang10@mtu.edu -s L_1 is finished;
now, the command arriving to the remote shell does not contain any quotes, because they have been removed by the local shell. In this particular case most of the arguments (except for the subject for
mutt) contain anything that needs to be quoted. However, we were using some variables, which didn't, but could have in general case contained spaces. Keep in mind that some day in the future you may decide to change the values of the variables in the script into something that happens to contain spaces. Then your script will stop working and you will have to read through it and put quotes wherever they are needed. So it's considered a good practice to treat variables as something that contains spaces even if they don't right now, to keep your code maintainable.
But there is a problem: the double quotes do not nest and they get removed by the local shell, so we need to protect them so they can survive their way to the remote shell. The most straight-forward way to do that is to escape them:
Code:
ssh -f "${host_list[0]}" "cd \"$address\" && nohup Rscript \"${program[0]}.R\" > \"${program[0]}_sh.txt\" ; echo \"The job ${program[0]} is finished\" | mutt zwang10@mtu.edu -s \"${program[0]} is finished\";"
Looks a little ugly, but should get the job done. What happens now? The outter quotes will be removed just like before, but the escaped quotes will not be interpreted. Instead, each occurence of a backslash followed by a double quote will be replaced by a literal double quote. So, now the string that gets to the remote shell is:
Code:
cd "/home/campus27/zwang10/Desktop/AWRR/program/power/vmodel_1/nprot/K_10" && nohup Rscript "L_1" > "L_1_sh.txt" ; echo "The job L_1 is finished" | mutt zwang10@mtu.edu -s "L_1 is finished";
Instead of double quotes, we could have just as well used single quotes for the inner quoting, because all the variables have already been expanded (We would need double quotes here if we had variables which we actually wanted to be expanded on the remote host). Even better -- because single quotes lose their special meaning within double quotes -- we don't even need to quote them:
Code:
ssh -f "${host_list[0]}" "cd '$address' && nohup Rscript '${program[0]}.R' > '${program[0]}_sh.txt' ; echo 'The job ${program[0]} is finished' | mutt zwang10@mtu.edu -s '${program[0]} is finished';"
So the command executed by the remote shell is
Code:
cd '/home/campus27/zwang10/Desktop/AWRR/program/power/vmodel_1/nprot/K_10' && nohup Rscript 'L_1.R' > 'L_1_sh.txt' ; echo 'The job L_1 is finished' | mutt zwang10@mtu.edu -s 'L_1 is finished';