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.

2 Answers 2


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.


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
  • 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, 2019 at 11:31

You must log in to answer this question.

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