I know that

sh -c 'echo $1' sh 4

will output 4. and

sh -c 'echo $2' sh 4 5

will output 5.

But I cannot understand how the parameters after the second sh were passed to the command next to sh -c. I read the man page of both bash and dash but could not find the introduction about this kind of syntax.


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.

In your command the second sh is just a parameter with position 0 while 4 has position 1 and so on.

You can run this to check:

$ sh -c 'echo $0' sh 4 5
| improve this answer | |
  • That seems to be the text in Bash's man page. It's actually incorrect in that it implies that $0 is one of the positional parameters. It isn't. The POSIX definition states that "A positional parameter is a parameter denoted by the decimal value represented by one or more digits, other than the single digit 0.", and Bash's manual itself contains that same definition. – ilkkachu Jan 7 '19 at 11:31

This behavior is actually specified by POSIX standard, which all Bourne-like shells should support to claim themselves portable.

sh -c [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]... command_string [command_name [argument...]]

See the command_string parameter ? Now let's look at -c flag description:


Read commands from the command_string operand. Set the value of special parameter 0 (see Special Parameters) from the value of the command_name operand and the positional parameters ($1, $2, and so on) in sequence from the remaining argument operands. No commands shall be read from the standard input.

In other words, where in normal shell script $0 (which is usually shell name in interactive mode or script name when you run a script) would be set by the shell itself, with -c you have to specify it yourself. Thus,

sh -c 'echo Hi, I am $0 , my first positional parameter is $1' foobar 5

would set the process name to sh foobar.

Just in case you're wondering what $0 is, it's also covered in "Special Parameters" section of Shell Command Language Specifications:


(Zero.) Expands to the name of the shell or shell script.

| improve this answer | |

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.