/bin/sh -c echo helloworld
runs the command echo
, which prints a blank line. You meant to type:
/bin/sh -c "echo helloworld"
which runs the command echo helloworld
.
The -c
option to sh
causes the first non-option argument to be treated as a string of commands to run in a new shell. The remaining arguments are used to fill in the that shell's numbered arguments, starting with $0
(the "name" under which the shell process is running.) These arguments are not automatically parsed to any utility executed by that shell.
So if you invoke sh
with /bin/sh -c echo helloworld
:
- the input passed to the shell interpreter
sh
is simply echo
helloworld
becomes $0
in the sh
session.
Normally, $0
in a shell invocation should be the name of the shell; that's what it will be set to by default:
bash$ /bin/sh
$ echo $0
/bin/sh
$ exit
bash$ echo $0
bash
Since the command given to the shell by -c
is interpreted as though it were input to the shell itself, you can use $n
in the command in order to refer to the extra arguments to the shell interpreter. If you want to do that, you need to remember to single-quote the -c
option argument so that it's contents are not interpreted by the outer shell. Perhaps studying the following will help:
bash$ /bin/sh -c 'echo $0' fakename # Correctly single-quoted
fakename
bash$ /bin/sh -c "echo $0" fakename # Here, $0 is expanded by the outer shell
bash
bash$ /bin/sh -c 'echo "$@"' sh arg1 arg2 arg3 # $0 is not part of $@
arg1 arg2 arg3