Exploring Bash getopts
Introduction
Bash has a builtin command getopts
for parsing parameters given as options (i.e -v, -e). getopts
can only parse
single character arguments that starts with -. GNU style options (i.e. –version) should be parsed manually or with
other command.
Usage
getopts
has the following signature:
getopts OPTSTRING VARIABLE [ARG...]
OPTSTRING is possible options as string. Each time getopts
is invoked it parses an ARG character using
OPTSTRING. If ARG is omitted getopts
parses positional parameters (i.e. $1 - $9).
OPTSTRING accepts any uppercase, lowercase, number and most special characters as option. When it starts with colon (:), error reporting is turned off. If colon (:) is added after a option/character then that options must have value.
OPTSTRING Example:
vn
- Accepts -v and -n options. -vn or -nv is also possible. If any invalid options is given prints an
error message.
:vn
- Accepts same options as vn
, error reporting is turned off as prefixed with colon (:).
vn:
- Accepts same -v option, but -n now expects value, (i.e. -n3 or -n 3 or -vn3 or -vn 3).
getopts
has 3 predefined variables:
Name | Description |
---|---|
OPTIND |
Index of next argument to process. It is initialized to 1 when shell starts |
OPTARG |
If options accepts value, then its put on this variable |
OPTERR |
Defaults to 1, stops error reporting when 0 |
getopts
fails when all options is parsed. So its can be written with loop:
#!/bin/bash
# filename: getopts-test.sh
while getopts "vn:" NAME; do
printf "NAME: %s, OPTIND: %d, OPTARG: %s\n" $NAME $OPTIND $OPTARG
done
# if run as ./getopts-test.sh -v -n 3
# NAME: v, OPTIND: 2, OPTARG:
# NAME: n, OPTIND: 4, OPTARG: 3
# if run as ./getopts-test.sh -vn3
# NAME: v, OPTIND: 1, OPTARG:
# NAME: n, OPTIND: 2, OPTARG: 3
# if run as ./getopts-test.sh -zn3
# getopts-test.sh: illegal option -- z
# NAME: ?, OPTIND: 1, OPTARG:
# NAME: n, OPTIND: 2, OPTARG: 3
When error reporting is off, invalid character is put in OPTARG and ?
is put in NAME.
#!/bin/bash
# filename: getopts-test.sh
while getopts ":vn:" NAME; do
printf "NAME: %s, OPTIND: %d, OPTARG: %s\n" $NAME $OPTIND $OPTARG
done
# if run as ./getopts-test.sh -zn3
# NAME: ?, OPTIND: 1, OPTARG: z
# NAME: n, OPTIND: 2, OPTARG: 3
Its helpful to use getopts
with case statement.
#!/bin/bash
# filename: getopts-test.sh
while getopts ":vn:" NAME; do
case "$NAME" in
v) echo "Version 1.00" ;;
n) echo "n:" $OPTARG ;;
*) echo "Invalid argument";;
esac
done
# shift parsed parameters
shift $(( OPTIND - 1 ))
# if run as ./getopts-test.sh -v -n 3 -z
# Version 1.00
# n: 3
# Invalid argument
Tools Version
- bash 4.4.19(1)-release