Have you ever passed several parameters to a command like this: ls -lah , and thought “I wish my bash scripts could parse command line parameters like that.” Allow me to introduce you to a bash function named getopts. Reader, meet getopts; getopts, meet reader.

The function getopts iterates through all command line parameters, evaluating if they match an expected parameter set. It takes two arguments: a string representing allowed parameters and a variable name to use while iterating through arguments. Here’s an example that should explain things:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #!/bin/bash # #file name: getopts.sh # #Sample script that takes two parameters, a, b, c, and v using getopts. #Parameters a and c are simple on/off switches #The b parameter takes a value. #The v parameter will be used to keep track of a verbosity level; # more '-v's results in a higher verbosity level # usage=$( cat <<EOF $0 [OPTION] -a set the "a" flag -b VALUE set "b" argument to VALUE -c set the "c" flag -v increase verbosity (-v = verbosity level 1; -vv = verbosity level 2; ...) EOF ) #define default values AFLAG_DEFAULT="off" BFLAG_DEFAULT="" CFLAG_DEFAULT="off" verbosity=0 #getopts returns success if an option is found and failure otherwise #so looping on it results in parsing all command line parameters #ab:cv is how we represent the flags to be accepted while getopts "ab:cv" OPTION; do case "$OPTION" in a) AFLAG="on" ;; b) #the colon after b in the args string above signifies that # b should be accompanied with a user-defined value. #that value will be stored in the OPTARG environment variable BFLAG="$OPTARG" ;; c) CFLAG="on" ;; v) #each -v should increase verbosity level verbosity=$(($verbosity+1)) ;; *) echo "unrecognized option" echo "$usage" ;; esac done #setting default values: #this command will set VARIABLE to DEFAULT_VALUE if it is currently # undefined, then return VARIABLE #${VARIABLE=DEFAULT_VALUE} #use a : to prevent bash from attempting to execute the value of # VARIABLE when it is returned : ${AFLAG=$AFLAG_DEFAULT} : ${BFLAG=$BFLAG_DEFAULT} : ${CFLAG=$CFLAG_DEFAULT} #verbosity doesn't need a default value; it was initialized to 0 above. #show the values as read in by the flags cat <<EOF a: $AFLAG b: $BFLAG c: $CFLAG verbosity: $verbosity EOF

Here are some sample runs to demonstrate the flexibility in how arguments can be passed:

Everything as a separate flag

1 2 3 4 5 $ ./getopts.sh -a -b aardvark -c -v -v -v a: on b: aardvark c: on verbosity: 3

All flags grouped together for the same effect (order does not matter)

1 2 3 4 5 $ ./getopts.sh -vvvacb aardvark a: on b: aardvark c: on verbosity: 3

Some flags grouped, some separated; default values used for missing arguments