bash

when to use bash with option -c?


I'm trying to understand -c option for bash better. The man page says:

-c: If the -c option is present, then commands are read from the first non-option argument command_string. If there are arguments after the command_string, they are assigned to the positional parameters, starting with $0.

I'm having trouble understanding what this means.

If I do the following command with and without bash -c, I get the same result (example from http://www.tldp.org/LDP/abs/html/abs-guide.html):

$ set w x y z; IFS=":-;"; echo "$*"
w:x:y:z
$ bash -c 'set w x y z; IFS=":-;"; echo "$*"'
w:x:y:z

Solution

  • bash -c isn't as interesting when you're already running bash. Consider, on the other hand, the case when you want to run bash code from a Python script:

    #!/usr/bin/env python
    import subprocess
    fileOne='hello'
    fileTwo='world'
    
    p = subprocess.Popen(['bash', '-c', 'diff <(sort "$1") <(sort "$2")',
                          '_',     # this is $0 inside the bash script above
                          fileOne, # this is $1
                          fileTwo, # and this is $2
                         ])
    print p.communicate() # run that bash interpreter, and print its stdout and stderr
    

    Here, because we're using bash-only syntax (<(...)), you couldn't run this with anything that used POSIX sh by default, which is the case for subprocess.Popen(..., shell=True) or os.system(...); using bash -c thus provides access to capabilities that wouldn't otherwise be available without playing with FIFOs yourself.


    Incidentally, this isn't the only way to do that: One could also use bash -s, and pass code in on stdin. Below, that's being done not from Python but POSIX sh (/bin/sh, which likewise is not guaranteed to have <(...) available):

    #!/bin/sh
    
    # ...this is POSIX sh code, not bash code; you can't use <() here
    # ...so, if we want to do that, one way is as follows:
    
    fileOne=hello
    fileTwo=world
    
    bash -s "$fileOne" "$fileTwo" <<'EOF'
    # the inside of this heredoc is bash code, not POSIX sh code
    diff <(sort "$1") <(sort "$2")
    EOF