4

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.

dessert
  • 40,956

2 Answers2

6

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:

-c

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:

0

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

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.

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
sh
dessert
  • 40,956
eyadof
  • 1,494