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?


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
    Jan 5 '16 at 16:33
  • 1
    sh -c 'echo "$@"' fnord a b c d ...
    – zwol
    Jan 5 '16 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
    Jan 5 '16 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
    Jan 5 '16 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
    Apr 17 '20 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.