Friday, December 28, 2012

getopts in shell programming


getopts is shell builtin command is used to parse command line arguments.

getopts takes an option string as an argument. The option string is as follows
  • Simple flag with no arguments - Just the letter of the flag like say for example, "-f
  • Flag with arguments - Letter of the flag followed by a colon. Say for example, if something like "-f filename", we would add "f:" to the option string.
getopts also supports detection of unknown flags and missing arguments. To enable this option, a colon(:) should be added as the first character of the option string.

The getopts returns a colon when it encounters a flag with missing argument.
getopts routine returns a question mark when it encounters an unknown flag.

getopts will set an exit status of FALSE when there is nothing left to parse. So it is easier to use getopts in a while loop

while getopts …; do
   …
done

getopts will parse options and their possible arguments. It will stop parsing on the first non-option argument (a string that doesn't begin with a hyphen (-), a string that isn't an argument for an option in front of it). It will also stop parsing when it sees the -- (double-hyphen), which stands for ends of options.

Variables associated with getopts
  • OPTIND - It holds the index of the next argument to be processed. OPTIND is initially set to 1, and should be reset to 1 if we need to parse anything again with getopts.
  • OPTARG - The argument value associated with the current flag(if any).
  • OPTERR - It takes values 0 or 1. It indicates if bash shell should display error messages generated by getopts built-in.  If this variable is set to 1, error reporting by the underlying getopts function is enabled. If set to 0, error reporting is disabled. This variable is ignored if the first character of the option string is a colon(:), which tells getopts that the script can handle and report errors.

Let us demonstrate with following example


#!/bin/bash

while getopts ":f" opt
do
   if [ $opt = "f" ]
   then
         echo "-f was triggered"
   fi
   if [ $opt = "?" ]
   then
         echo "Invalid option flag: -$OPTARG"
         #exit 1
   fi
done 

Calling it without arguments

$ ./opt.sh

getopts did not see any valid or invalid options

Calling with non option arguments

$ ./opt.sh /etc/passwd
$

Again, getopts did not see any valid or invalid options

Calling with option arguments

$ ./opt.sh -f
-f was triggered

The "f" was put into variable $opt

Suppose an invalid argument is passed as an argument
$ ./opt.sh -a
Invalid option flag: -a

getopts did not accept the option "a" and acted by putting ? into $opt and the invalid option character(a) into $OPTARG.

It is possible to mix valid and invalid options

$ ./opt.sh -a -b -f -c
Invalid option flag: -a
Invalid option flag: -b
-f was triggered
Invalid option flag: -c

It is also possible to give valid option multiple times

$ ./opt.sh -f -f -f
-f was triggered
-f was triggered
-f was triggered

Now let us consider passing arguments for flags


Arguments can be passed to flags by placing a colon(:) after the flag

#!/bin/bash

while getopts ":f:" opt
do
   if [ $opt = "f" ]
   then
         echo "-f was triggered with parameter $OPTARG"
   fi
   if [ $opt = "?" ]
   then
         echo "Invalid option flag: -$OPTARG"
         #exit 1
   fi
   if [ $opt = ":" ]
   then 
         echo "Option flag $OPTARG requires an argument"
   fi
done 

Calling without an argument for the flag

$ ./optarg.sh -f
Option flag f requires an argument

Calling with a valid argument for the flag

$ ./optarg.sh -f /etc/passwd
-f was triggered with parameter /etc/passwd

No comments:

Post a Comment