(Default) arguments in bash script

Estimated reading time of this article: 3 minutes

How to handle default values with script arguments/parameters?
How to handle optional arguments with and without right-hand values?

I have several bash scripts depending on optional arguments. I want to minimize my typing and error sources.

There are three cases that I want to handle:

  • 1) Parameter is not present: the global default value has to be taken
  • 2a) Parameter is present, but no right-hand value is given (-x or -x=): the parameter default value has to be taken
  • 2b) Parameter is present, but only an equal sign is given without value (-X=): the empty string should be set
  • 3) Parameter is present with given value (-x=Y): the value has to be taken

The following script implements this behavior and serves as a demo. This small script is also published on GitHub Gist as args.sh.

#!/bin/bash

# Bash optional arguments demo

# Three cases are supported:
# 1) Parameter is not present: the global default value is taken
# 2a) Parameter is present, but no right-hand value is given (-x or -x=): the parameter default value is taken
# 2b) Parameter is present, but only an equal sign is given without value (-X=): the empty string is set
# 3) Parameter is present with given value (-x=Y): the value is taken
# 4) Left over parameters are output in verbose mode (-v)

# ./args.sh
# x='X'

# ./args.sh -x
# x='Y'

# ./args.sh -x=Z
# x='Z'

# ./args.sh -x=
# x='Y'

# ./args.sh -X=
# x='X'

# ./args.sh --demox
# x='Y'

# ./args.sh --demox=Z
# x='Z'

# ./args.sh -x -v
# x='Y'
# Remaining arguments: ''

# ./args.sh -x -v -a -b c abc
# x='Y'
# Remaining arguments: '-a -b c abc'

x='X'
verbose=false

POSITIONAL=()
while test $# -gt 0; do
    case $1 in
        -h|--help)
            echo "Args demo: prints value of argument x"
            echo
            echo "$0 [options]"
            echo
            echo "Options:"
            echo "-x[=VAL], --demox[=VAL]   Demo argument, default 'X' if parameter not present, default 'Y' if -x is given without right-hand value"
            echo "-X[=VAL], --demoX[=VAL]   Demo argument, default 'X' if parameter not present, default 'Y' if -X is given without right-hand value (treating -X= as empty value)"
            echo "-v, --verbose             Verbose mode: show remaining arguments"
            echo "-h, --help                Show this help"
            echo
            exit
        ;;
        -x|--demox|-X|--demoX)
            x="Y"
            shift
        ;;
        -x=*|--demox=*)
            x="${1#*=}"
            if [[ $x == "" ]]; then
                x="Y"
            fi
            shift
        ;;
        -X=*|--demoX=*)
            x="${1#*=}"
            shift
        ;;
        -v|--verbose)
            verbose=true
            shift
        ;;
        *)
            POSITIONAL+=("$1") # save it in an array for later
            shift
        ;;
    esac
done

set -- "${POSITIONAL[@]}" # restore positional parameters

echo "x='$x'"

if $verbose; then
    echo "Remaining arguments: '$@'"
fi