Easy getopt for a BASH script


getopt is extremely useful for quickly being able to add options and arguments to your program without having to worry much about the parsing yourself. There are getopt libraries for many languages but what about BASH? It turns out there are actually two versions of getopt that you can use in your BASH scripts; a command line utility getopt provided by the util-linux package, and a bash builtin getopts. I have provided a brief overview of each in the following sections.

getopt: The command line utility


An example of a bash script using getopt to allow the user to specify one of three colors (blue, red, or green) is shown below. The user can specify -b to imply the color is blue or can specify --color=blue to do the same. If the user uses the long option --color they must specify an argument to denote what color.

#!/bin/bash # Call getopt to validate the provided input. options=$(getopt -o brg --long color: -- "$@") [ $? -eq 0 ] || { echo "Incorrect options provided" exit 1 } eval set -- "$options" while true; do case "$1" in -b) COLOR=BLUE ;; -r) COLOR=RED ;; -g) COLOR=GREEN ;; --color) shift; # The arg is next in position args COLOR=$1 [[ ! $COLOR =~ BLUE|RED|GREEN ]] && { echo "Incorrect options provided" exit 1 } ;; --) shift break ;; esac shift done echo "Color is $COLOR" exit 0;

And here are the outputs from some test runs:

dusty@media: content>./test -b Color is BLUE dusty@media: content>./test -r Color is RED dusty@media: content>./test -g Color is GREEN dusty@media: content>./test -z getopt: invalid option -- 'z' Incorrect options provided dusty@media: content>./test --color=BLUE Color is BLUE dusty@media: content>./test --color getopt: option '--color' requires an argument Incorrect options provided dusty@media: content>./test --color=YELLOW Incorrect options provided

getopts: The bash builtin


We can almost exactly perform the same task with the getopts builtin. Unfortunately the getopts builtin does not support long options so I created a new -c short option and added a : to the line to specify that it takes an argument (just like --color from the first example). The code is shown below. Notice that getopts actually uses the $OPTARG variable for options that have arguments which makes for easy to read code.

#!/bin/bash while getopts "brgc:" OPTION; do case $OPTION in b) COLOR=BLUE ;; r) COLOR=RED ;; g) COLOR=GREEN ;; c) COLOR=$OPTARG [[ ! $COLOR =~ BLUE|RED|GREEN ]] && { echo "Incorrect options provided" exit 1 } ;; *) echo "Incorrect options provided" exit 1 ;; esac done echo "Color is $COLOR" exit 0;

And finally a similar set of output from test runs:
dusty@media: content>./test2 -b Color is BLUE dusty@media: content>./test2 -r Color is RED dusty@media: content>./test2 -g Color is GREEN dusty@media: content>./test2 -z ./test2: illegal option -- z Incorrect options provided dusty@media: content>./test2 -c BLUE Color is BLUE dusty@media: content>./test2 -c ./test2: option requires an argument -- c Incorrect options provided dusty@media: content>./test2 -c YELLOW Incorrect options provided dusty@media: content>

Cheers!

Dusty Mabe