For example, while this works:

$ echo foo

This doesn't:

$ /bin/sh -c echo foo

Whereas this does:

$ /bin/sh -c 'echo foo; echo bar'

Is there an explanation?

4 Answers 4


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 


$ 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.

  • 2
    A stricter, standard conformant way would be sh -c 'echo $1' echo foo
    – jlliagre
    Commented Jan 5, 2016 at 16:33
  • 1
    sh -c 'echo "$@"' fnord a b c d ...
    – zwol
    Commented Jan 5, 2016 at 17:43
  • 3
    IMHO the explanation was quite good, but sh -c 'echo $0' foo is not the best option, taking into account that the questioner already know that /bin/sh -c 'echo foo; echo bar' works, you can simply answer quoting the command /bin/sh -c 'echo foo'
    – X3MBoy
    Commented Jan 5, 2016 at 18:01
  • 1
    @ X3MBoy The questioner already know that /bin/sh -c 'echo foo' works fine. He wanted to echo something outside that , which i explained
    – Ijaz Ahmad
    Commented Jan 5, 2016 at 18:18
  • @IjazAhmadKhan what if I want to execute some command with sh -c something like this: sh -c test.py arg1 arg2 arg3 ? Secondly what if arg3 contains something like "/export/local/repo/ab#cd.rpm" , how can I handle # in this case ?
    – Subhajit
    Commented Apr 17, 2020 at 10:51
$ echo 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'

The shell is invoked with the argument echo foo; echo bar which outputs


In this command:

echo foo

echo is the binary (or built-in command) and foo is the first argument.


/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".


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" "$@"' zero one two three
args = zero one two three


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
$ /bin/sh -c "echo foo"
$ /bin/sh -c 'echo foo'


Keep the executed command as one "word" using quoting.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .