Consider a tool like
watch that can take another command (e.g.
ls -l) like this:
watch ls -l # or equivalently watch 'ls -l'
If the command is more complicated, it's all about quoting/escaping if things like
&& are interpreted by the current shell or get to
watch. These two commands are different:
watch echo "$$" watch 'echo "$$"'
So are these:
watch date ; echo done watch date \; echo done
ssh is similar, it can take one or more arguments and built a command to be run on the server. It depends on quoting/escaping if the local shell interprets
| and such, or the remote shell.
And there are commands like
sh -c which require a single argument containing code, but the need for quoting/escaping is similar. In fact
ssh) builds this single argument for
sh -c or similar command.
I already have the exact command I want to provide to
ssh, or similar tool. The command is obtained from history or pasted into the command line or typed as if it's going to be executed directly; it's in my command line verbatim. Nothing in the command should be expanded or interpreted before it gets to
watch or similar tool. In case of
watch it means all the expansion and interpretation should occur later, periodically. In case of
ssh it means it should occur on the server.
Now I need to do two things:
watch(or whatever) at the beginning. This is not a problem. I can do this last.
Quote and/or escape the original command. In general the command can include single-quotes, so just embracing with single-quotes blindly is not a solution. I think I know the right general solution:
- replace every
- embrace the whole resulting string with single-quotes;
but it's tedious and error-prone to do this by hand.
- replace every
Can I make Bash properly add one level of single-quoting/escaping to the entire command line on demand?
(Note: the question arose when I was answering this one.)