Bash: Script options parsing with getopts
How to use getopts
The man page for getopts can be found here
When writing bash scripts it can be useful to accept arguments to alter the behavior of your script. Parsing arguments by hand is not hard, but not fun to repeat in various scripts. I learned today that there is a built in function for this called getopts!
The syntax for using getopts is getopts optstring name
getopts can be used with a while loop in a bash script to parse all options in a loop, We will see an example of that below.
optstring argument
Where optstring is a string that tells getopts what your arguments are called. Colons : are also used to denote that an argument also takes a value. If the optstring starts with a : then errors and other logs are suppressed from getopts. Here are some examples
abcais a flag that does not take a valuebis a flag that does not take a valuecis a flag that does not take a value
abc:ais a flag that does not take a valuebis a flag that does not take a valuecis a flag that does take a value
:abc:- The first
:suppresses errors from getopts ais a flag that does not take a valuebis a flag that does not take a valuecis a flag that does take a value
- The first
The optstring parses arguments that follow the POSIX.1‐2017 12.2 Utility Syntax Guidelines 3 through 10
These guidelines are worth a ready, but a notable part of the guidelines is that options must be prepended with a - and be only one character. For example -a for a flag and -c value for options that take a value.
name argument
The name argument is the name of the shell variable that will be set to the option character that was found.
Shell Variables of Note
OPTARG- This is the shell variable that hold the value of the option parsed by
getoptsif the option being parsed has a:after it inoptstring
- This is the shell variable that hold the value of the option parsed by
OPTIND- This is the index of the last option parsed by
getopts. It can be useful in various ways. See the example script below!
- This is the index of the last option parsed by
Example Script
#! /bin/bash
aflag=
bflag=
cflag=
dflag=
echo_getopts_vars() {
# This prints out the relevant variables used by getopts
# so we can see them at any given point in time.
echo "name = $name"
echo "OPTARG = $OPTARG"
echo "LANG = $LANG"
# echo "LC_ALL = $LC_ALL"
# echo "LC_CTYPE = $LC_CTYPE"
# echo "LC_MESSAGES = $LC_MESSAGES"
# echo "NLSPATH = $NLSPATH"
echo "OPTIND = $OPTIND"
}
printf "pre getopts call values:\n"
echo "-----"
echo_getopts_vars
echo "-----"
# printf "\n"
loopcount=0
# : as the first char in the optstring suppresses errors from getopts
while getopts :ab:cd: name
do
printf "\npost getopts call %d\n" "$loopcount"
echo "-----"
echo_getopts_vars
case $name in
a) aflag=1;;
b) bflag=1
bval="$OPTARG";;
c) cflag=1;;
d) dflag=1
dval="$OPTARG";;
?) printf "Usage: %s: [-a] [-b value] [-c] [-d value] args\n" $0
exit 2;;
esac
loopcount=$[$loopcount+1]
echo "-----"
done
printf "\n"
# If the -a options is present
if [ ! -z "$aflag" ]; then
printf "Option -a specified\n"
fi
# if the -b options is present with a value provided
if [ ! -z "$bflag" ]; then
printf 'Option -b "%s" specified\n' "$bval"
fi
# If the -c options is present
if [ ! -z "$cflag" ]; then
printf "Option -c specified\n"
fi
# if the -d options is present with a value provided
if [ ! -z "$dflag" ]; then
printf 'Option -d "%s" specified\n' "$dval"
fi
# This shift is using the OPTIND variable managed by getopts to shift the
# arguments over such that only the items not processed by getopts
# will remain in $*
shift $(($OPTIND - 1))
printf "Remaining arguments are:\n-----\n%s\n-----\n" "$*"