====== Handling Command Line Options (getopts) ====== Most Unix command line utilities we have looked at provide multiple command line options. Some of them, such as [[cs_370_-_file_network_and_version_utilities#archiving_and_compression|tar]] allow you to flexibly combine command line options to modify command behavior in multiple ways at once. The shell (bash) provides the //getopts// construct that allows you to add flexible command line option handling to shell scripts. ===== The getopts construct ===== Sample script #1 that uses getopts: #!/bin/bash # getopts_test1 # This script has 3 command line options, one of which takes an argument. function usage { echo "script usage: $(basename $0) [-l] [-m] [-o somevalue]" >&2 exit 1 } while getopts 'lmo:' OPTION; do case "$OPTION" in l) echo "option l selected" ;; m) echo "option m selected" ;; o) oarg="$OPTARG" echo "The o option's argument was $oarg" ;; ?) usage ;; esac done shift "$(($OPTIND - 1))" * The //getopts// command is used as the condition of a while loop. * The string after getopts, 'lmo:', contains the single letter options that the script accepts. * Here, they are l, m and o. * 'lmo:' is called an //optstring//. * Within the loop, in a [[cs_370_-_shell_scripting#the_case_structure | case structure]], define what to do with the options that the script will accept. * Notice the colon after the last option in 'lmo:'. It is the way we tell getopts that the option o requires an argument. * When the shell script is running, each parsed option will be stored inside the $OPTION variable, while an argument, when present, will become the value of the $OPTARG variable. * Each option is managed inside the case statement, with a final ? case that will be matched whenever an invalid option is found. In that case we will just echo the user the correct script usage and exit with an error code. * When the shell script is running, //getopts// looks for a dash (-) and a letter or a series of letters that follow the -. It parses the letters as command line options. * Valid ways to call the above script: ./getopts_test1 -l -m ./getopts_test1 -l -m -o 3 ./getopts_test1 -lm ./getopts_test1 -lm -o 3 ./getopts_test1 -lmo 3 ./getopts_test1 -lmo3 ./getopts_test1 -o 3 -l -m ./getopts_test1 -o3 -lm ./getopts_test1 -o3 -m (and more) * The $OPTIND variable contains the number of command line option arguments that //getopts// parsed. ./getopts_test1 -o 3 -l -m # $OPTIND = 4 ./getopts_test1 -o3 -lm # $OPTIND = 4 ./getopts_test1 -l -m # $OPTIND = 2 ./getopts_test1 -lm # $OPTIND = 2 * shift "$(($OPTIND - 1))" * The [[cs_370_-_shell_scripting#the_while_structure|shift]] command is a shell built-in command which moves the [[cs_370_-_shell_scripting#special_built-in_script_variables|positional parameters]] of the script down a specified number of positions, discarding the related arguments. * Running shift "$(($OPTIND - 1))" discards the command line options; this is a standard thing to do in a shell script using //getopts//, when the command line options are no longer needed. ==== Command line options plus additional arguments ==== Sample script #2 that uses getopts: #!/bin/bash # getopts_test2: # This script has 3 command line options and # takes an additional script argument ($1) while getopts dmy OPTION do case $OPTION in d) dopt=1;; m) mopt=1;; y) yopt=1;; ?) echo "Unrecognized or invalid option" exit 1;; esac done if [ ! -z $dopt ]; then day=$(date '+%d') fi if [ ! -z $mopt ]; then mon=$(date '+%b') fi if [ ! -z $yopt ]; then year=$(date '+%Y') fi shift $(($OPTIND - 1)) echo "The date is: $day $mon $year" if [ ! -z $1 ]; then echo "Welcome, $1." fi * To display day, month, year and a "Welcome" message, run the script in one of the following ways: ./getopts_test2 -d -m -y Dave ./getopts_test2 -dmy Dave * Without doing 'shift $(($OPTIND -1 ))' to discard the command line options, the script would not be able to properly process the additional command line argument ($1). ==== Example: text2png_getopts ==== Test a version of the text2png script that uses getopts for command line options handling: [[https://cssegit.monmouth.edu/jchung/csse370repo/-/blob/main/scripts/text2png_getopts|text2png_getopts]]