Why doesn’t echo called as /bin/sh -c echo foo output anything?

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

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x