Search code examples
bashsh

Why getting blank output when running "/bin/sh" with "-c" option


I am running /bin/sh with -c option as below but getting a blank output:

[root@dockerhost dproj]# /bin/sh -c echo helloworld
[root@dockerhost dproj]#

Why the above command is not printing helloworld?

I have tried to read the man page but not able to understand anything.

From man sh:

   -c        Read  commands  from the command_string operand. 
             Set the value of special parameter 0 
             (see Section 2.5.2, 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.

Solution

  • /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