For example, while this works:
$ echo foo foo
This doesn’t:
$ /bin/sh -c echo foo
Whereas this does:
$ /bin/sh -c 'echo foo; echo bar' foo bar
Is there an explanation?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
From man sh
-c string If the -c option is present, then commands are read from string.
If there are arguments after the string, they are assigned to the
positional parameters, starting with $0
It means your command should be like this:
$ sh -c 'echo "$0"' foo foo
Similarly:
$ sh -c 'echo "$0 $1"' foo bar foo bar
That was the first part to understand; the second case is simple and doesn’t need explanation, I guess.
Method 2
$ echo foo foo
This calls echo with the argument foo and foo is printed.
$ /bin/sh -c echo foo
This invokes the shell with the argument echo and provides foo as argument
$0. The echo outputs a new line and you discard the foo. If you want to
output foo, quote the argument:
sh -c 'echo foo'
or use the provided argument:
sh -c 'echo $0' foo
In this example
$ /bin/sh -c 'echo foo; echo bar' foo bar
The shell is invoked with the argument echo foo; echo bar which outputs
foo bar
Method 3
In this command:
echo foo
echo is the binary (or built-in command) and foo is the first argument.
Here:
/bin/sh -c echo foo
/bin/sh is the binary, whose first argument is -c, which itself accepts a “command string” as parameter. This is echo in the above example. Then there is a third argument: foo which is an argument for /bin/sh, not for echo. That’s why in your third example:
/bin/sh -c 'echo foo; echo bar'
… both are printed. You quoted the argument. Thus: the first argument is -c, and the parameter to this argument is 'echo foo; echo bar' which is interpreted whole as one argument; as the “command string”.
Method 4
The structure sh -c word executes only word (in a shell).
Added words mean other things, like argument zero, one, two, etc.:
sh -c word zero one two three
to keep a command which has spaces as one word, quoting is needed:
sh -c 'echo fnord' zero one two three
so, this prints all the arguments:
$ sh -c 'echo "args=" "$0" "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6c482c">[email protected]</a>"' zero one two three args = zero one two three
Examples
In the example you present: /bin/sh -c echo foo The first word (after options) is echo, that is what is executed. And an echo with no text will print a new-line only, nothing else:
$ /bin/sh -c echo foo
That is why you do get an empty line.
If you quote the space, you will be executing “one word” (no spaces), as this:
$ /bin/sh -c echo foo foo $ /bin/sh -c "echo foo" foo $ /bin/sh -c 'echo foo' foo
Conclusion
Keep the executed command as one “word” using quoting.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0