Search code examples
bashcommand-line-interfacegetopts

Boolean cli flag using getopts in bash?


Is it possible to implement a boolean cli option using getopts in bash? Basically I want to do one thing if -x is specified and another if it is not.


Solution

  • Of course it is possible. @JonathanLeffler already pretty much gave the answer in the comments to the question, so all I'm going to do here is add an example of the implementation and a few niceties to consider:

    #!/usr/bin/env bash
    
    # Initialise option flag with a false value
    OPT_X='false'
    
    # Process all options supplied on the command line 
    while getopts ':x' 'OPTKEY'; do
        case ${OPTKEY} in
            'x')
                # Update the value of the option x flag we defined above
                OPT_X='true'
                ;;
            '?')
                echo "INVALID OPTION -- ${OPTARG}" >&2
                exit 1
                ;;
            ':')
                echo "MISSING ARGUMENT for option -- ${OPTARG}" >&2
                exit 1
                ;;
            *)
                echo "UNIMPLEMENTED OPTION -- ${OPTKEY}" >&2
                exit 1
                ;;
        esac
    done
    
    # [optional] Remove all options processed by getopts.
    shift $(( OPTIND - 1 ))
    [[ "${1}" == "--" ]] && shift
    
    # "do one thing if -x is specified and another if it is not"
    if ${OPT_X}; then
        echo "Option x was supplied on the command line"
    else
        echo "Option x was not supplied on the command line"
    fi
    

    A few notes about the above example:

    • true and false are used as option x indicators because both are valid UNIX commands. This makes the test for the option presence more readable, in my opinion.

    • getopts is configured to run in silent error reporting mode because it suppressed default error messages and allows for a more precise error handling.

    • the example includes fragments of code for dealing with missing option arguments and post-getopts command line arguments. These are not part of the OP's question.

      They are added for the sake of completeness as this code will be required in any reasonably complex script.

    For more information about getopts see Bash Hackers Wiki: Small getopts tutorial