5 ms·
The article mentioned printf '%q ', but it is a bit hard to find. Here is a handy way to remember it. First, define this function: quote-argv() { printf
by chubot 1y ago
The article mentioned printf '%q ', but it is a bit hard to find. Here is a handy way to remember it.
First, define this function:
quote-argv() { printf '%q ' "$@"; }
# (uses subtle vectorization of printf over args)
Now this works correctly:
ssh example.com "$(quote-argv ls 'file with spaces')"
ls: cannot access 'file with spaces': No such file or directory
In contrast to:
$ ssh example.com ls 'file with spaces'
ls: cannot access 'file': No such file or directory
ls: cannot access 'with': No such file or directory
ls: cannot access 'spaces': No such file or directory
And yes the "hidden argv join" of ssh is VERY bad, and it is repeated in shell's eval builtin.
They should both only take a SINGLE arg.
It is basically a self-own because spaces are an OPERATOR in shell! (the operator that separates words)
When you concatenate operators and variables, then you are mixing code and data, which is a security problem.
---
As for the exec workaround, I think this is also deficiency of shell. Oils will probably grow an 'invoke' builtin which generalizes 'command' and 'builtin', which are non-orthogonal.
'command true' means "external or builtin" (disabling shell function lookup), but there should be something that means "external only".
- o11c 1y agoUse ' %q' and you also fix the problem of program names starting with a dash.
- chubot 1y agoAh yes, that's clever: $ sh -c "$(quote-argv -echo 'file with spaces')" sh: 0: Illegal option -h $ sh -c "$(quote-argv-left -echo 'file with spaces')" sh: 1: -echo: not found Over ssh: $ ssh example.com "$(quote-argv-left -dashtest 'file with spaces')" -dashtest file with spaces
- deleted 1y ago[deleted]
- blueflow 1y ago> hidden argv join It is not hidden. It is written down in plain sight: A complete command line may be specified as command, or it may have additional arguments. If supplied, the arguments will be appended to the command, separated by spaces, before it is sent to the server to be executed. - third line in `man 1 ssh`
- chubot 1y agoIt's hidden in the sense that it creates ambiguity at the usage site. Compare with sudo: $ sudo ls 'file with spaces' ls: cannot access 'file with spaces': No such file or directory If ssh (and sh eval) did not accept multiple arguments, then this wouldn't even get to ls: $ ssh example.com ls 'file with spaces' ls: cannot access 'file': No such file or directory ls: cannot access 'with': No such file or directory ls: cannot access 'spaces': No such file or directory Accepting argv is better. Or forcing this is better: $ ssh example.com "ls 'file with spaces'" So it's clear it's a single shell string. Accepting a shell string is sometimes OK, but silently joining multiple args is useless, and insecure. "RTFM" is not a good answer when security is involved.
- blueflow 1y agoThis stubborn attitude to refuse to consult the documentation at all and then expect the tool to work according to your preconceptions. Tools do have rough edges, if you don't want to learn about them, you will get bitten.