Classic Shell Scripting - Arnold Robbins [78]
done
After this loop has finished, the various flag variables are set, and may be tested using test or case. Any remaining nonoption arguments are still available for further processing in "$@".
The getopts command simplifies option processing. It understands the POSIX option conventions that allow grouping of multiple option letters together, and can be used to loop through command-line arguments one at a time.
* * *
getopts
Usage
getopts option_spec variable [ arguments ... ]
Purpose
To simplify argument processing, and make it possible for shell scripts to easily adhere to POSIX argument processing conventions.
Major options
None.
Behavior
When called repeatedly (such as in a while loop), step through the provided command-line arguments, or "$@" if none, exiting nonzero at -- or the first nonoption argument, or upon error. The option_spec describes options and their arguments; see the text for details.
For each valid option, set variable to the option letter. If the option has an argument, the argument value is placed in OPTARG. At the end of processing, OPTIND is set to the number of the first nonoption argument. See text for further details.
Caveats
The ksh93 version of getopts conforms to POSIX, but has many additional features. See the ksh93 documentation and Learning the Korn Shell (O'Reilly).
* * *
The first argument to getopts is a string listing valid option letters. If an option letter is followed by a colon, then that option requires an argument, which must be supplied. Upon encountering such an option, getopts places the argument value into the variable OPTARG. The variable OPTIND contains the index of the next argument to be processed. The shell initializes this variable to 1.
The second argument is a variable name. This variable is updated each time getopts is called; its value is the found option letter. When getopts finds an invalid option, it sets the variable to a question mark character. Here is the previous example, using getopts:
# set flag vars to empty
file= verbose= quiet= long=
while getopts f:vql opt
do
case $opt in Check option letter
f) file=$OPTARG
;;
v) verbose=true
quiet=
;;
q) quiet=true
verbose=
;;
l) long=true
;;
esac
done
shift $((OPTIND - 1)) Remove options, leave arguments
Three things are immediately noticeable. First, the test in the case is only on the option letter. The leading minus is removed. Second, the case for -- is gone: getopts handles that automatically. Third, also gone is the default case for an invalid option: getopts automatically prints an error message.
Often, though, it's easier to handle errors in the script than to use getopts's default handling. Placing a colon (:) in the option string as the first character makes getopts change its behavior in two ways. First, it won't print any error messages. Second, besides setting the variable to a question mark, OPTARG contains the invalid option letter that was provided. Here's the final version of the option processing loop:
# set flag vars to empty
file= verbose= quiet= long=
# leading colon is so we do error handling
while getopts :f:vql opt
do
case $opt in Check option letter
f) file=$OPTARG
;;
v) verbose=true
quiet=
;;
q) quiet=true
verbose=
;;
l) long=true
;;
'?') echo "$0: invalid option -$OPTARG" >&2
echo "Usage: $0 [-f file] [-vql] [files ...]" >&2
exit 1
;;
esac
done
shift $((OPTIND - 1)) Remove options, leave arguments
* * *
Warning
The OPTIND variable is shared between a parent script and any functions it invokes. A function that wishes to use getopts to parse its own arguments should reset OPTIND to 1. Calling such a function from within the parent script's option processing loop is not advisable. (For this reason, ksh93 gives each function its own private copy of OPTIND. Once again, caveat emptor.)
* * *
Functions
As in other languages, a function is a separate piece of code that performs some well-defined single task. The function can then be used (called) from multiple places within