Friday, September 17, 2010

Bash command line parameter parsing (getopts)

If I only need a single optional parameter I'll often just check to see if the input positional parameter of interest is set (e.g. script that accepts one required field and one optional field):

if [[ ! -n "$2" ]];
then
echo "I received the second parameter:$2"
fi

But if you want to do something a bit more complex, getopts is your friend.

For example, say you want to have the user input their first name, last name and a "keep my data private" flag you could do something like this:

while getopts f:l:p flag
do
case $flag in
f)
FIRSTNAME=$OPTARG;;
l)
LASTNAME=$OPTARG;;
p)
PRIVATE=1;;
?)
echo "$0 -f <first name> -l <last name> -p"
echo -e "\t-p [flag] keep my data private"
exit
done

The getopts command is fairly straightforward (man getopts for more details). If an option requires an argument then a colon is placed after it's letter designation ('f' and 'l' in the above example).

You can check for required parameters by looking at which variables were set:

if [[-z "$FIRSTNAME" || -z "$LASTNAME" ]];
then
echo "missing required parameter"
fi

Wrap that all up into a neat script with a subroutine that outputs a usage statement and you're home free:

function usage_and_exit()
{
echo "$0 -f <first name> -l <last name> -p"
echo -e "\t-p [flag] keep my data private"
exit
}

while getopts f:l:p flag
do
case $flag in
f)
FIRSTNAME=$OPTARG;;
l)
LASTNAME=$OPTARG;;
p)
PRIVATE=1;;
?)
usage_and_exit;;
done

if [[ -z "$FIRSTNAME" || -z "$LASTNAME" ]];
then
echo "missing a required parameter (firstname and lastname are required)"
usage_and_exit
fi

if [[ $PRIVATE -ne 0 ]];
then
echo "protecting private data"
fi