/ HowTos

BASH Arguments

So, I've written a few Bash scripts in my day. I'm by no means a Bash expert, but I get by.

In a few of my scripts, I try to add argument flags to add usability, but nothing really fancy. Just one flag here and there. I'm nowhere near the level of the tar command yet.

tar
Credit where credit is due

Normally I would just throw together a quick mess of case and if statements.

#runtime Flags
flags=$1

....

#-------------------------------------------------------------------------------
# Main Case Statement for setting flags 
#-------------------------------------------------------------------------------
case "$flags" in
     -y)
          answer=$flag;;
     -h)
          less .help;
          exit 0;;
     "")
          echo "No Flags" > /dev/null ;;
     *)
          echo "Invalid option.  Use -h for help";
          exit 0;;
esac

....

# Check the $flags for -y
# Later on in this code, it would check the $answer variable and
# mimic the behavior of `yum -y update` if $answer = "yes"
if [[ $flags == "-y" ]]
then
    answer="yes"
else
    echo -e "\nDo Something?  (Yes/No)"
    read -e answer
fi

This got the job done....but it's definitly not pretty. Then I stumbled on getopt(s). From the man pages - "getopts is used by shell procedures to parse positional parameters...."

This is what I love about Linux. I don't think I'll ever stop learning something new about it!

Enough chatter, on to the code!

usage(){
        echo "useful info on how to use this shell script"
}
if ( ! getopts ":gs:vh" opt); then
        usage
        exit 1
fi

options=':gs:vh'
while getopts $options option
do
    case $option in
        g  ) echo "-g used";;
        s  ) echo "-s used with $OPTARG";;
        v  ) echo "-v flag used";;
        h  ) usage; exit;;
        \? ) echo "Unknown option: -$OPTARG" >&2; exit 1;;
        :  ) echo "Missing option argument for -$OPTARG" >&2; exit 1;;
        *  ) echo "Unimplimented option: -$OPTARG" >&2; exit 1;;
    esac
done

No lets break this down. The usage() function simply echos info on the script. You can really have this do anything. For example, I have it cat the readme file.

The if statement checks to make sure an argument has been passed. If there is no argument passed at runtime, then it calls the usage() function and exits with a status of 1.

The options=':gs:vh' sets the list of valid run-time flags. As far as I can tell, the : at the beginning is needed always, or at least if any of the flags take an argument. It should be fine to just always have it there, though you might consult the man pages to be sure.
After the first :, if you specify a flag like s: that tells getopts that the -s flag requires an argument. (Example: -s somethinghere)
So to recap, the flags g, v, and h do not require arguments and -s requires one argument.

The while loop loops through the arguments passed and the case statement checks each argument against the valid options. In this example, if there is a valid match it simply executes an echo (valid matches are -g -s -v -h). You could (and should) do something more meaningful here, like set variables, run functions, or something else that is useful to the goal of your script.
It also checks if there are unkown options ?, missing arguments for flags that require them :, and unimplemented flags *.

I plan to implement this into my ugly scripts that use my old version of flag passing....because they need it.
HAPPY BASHING!!