Monday, November 24, 2008

Working with getopts and optargs in bash

Welcome to this weeks edition of Practical shell scripting. This weeks edition is about getopts and optargs in bash. In the last couple of weeks I was given a job to do at work that had a request to create a shell script that was capable of taking command line argument in the fashion of what C/C++ programmers would refer to as argv and argc. That is the arguments indicate what and how the following value will be used. This is typically depicted in a fashion like so:

#> ./foo -y 14

Where foo is the application or executable and -y tells you something about the next argument coming in. So maybe -y is for years or something else defined by the application foo internally and the value following -y is that value. This is easily done in the C programming language, but I had never done this in shell scripts, and while it seems straight forward there was a gotcha that I wanted to point out that hung me up a bit. So first here's a slice of example code to illustrate the basics of implementing getopts and optargs in a shell script. As with all shell scripts the # identifies lines which are not interpreted by bash either to be used as comments or to delineate the code in some fashion.


#!/bin/bash
###-----------------------------------------------------------###
# GetOptsExample.sh
# a small shell script to demonstrate getopts and optargs in bash
# --apg
#
###-----------------------------------------------------------------------------------###
PRODUCE=0

while getopts "a:o:b:" OPTION;
do
case $OPTION in
a)
## -a is for apples ##
echo "OPTION is a"
PRODUCE=$OPTARG
echo "The produce is $PRODUCE apples "
;;
o)
## -o is for oranges ##
echo "OPTION is o"
PRODUCE=$OPTARG
echo "The produce is $PRODUCE oranges"
;;
b)
## -b is for beans ##
echo "OPTION is b"
PRODUCE=$OPTARG
echo "The produce is $PRODUCE beans"
;;
esac
done


###--------------------------------------------------------------------------------------###

So what we see here is basically a simple case statement that uses the word OPTION as the flag for the case statement to differentiate which options are incoming as arguments. The optargs are then the parts that follow the options. This all seems fairly straight forward enough. However, the gotcha in my original attempts was quite sneaky. It seems that one critical aspect of the getopts line is the placement of the colon after each option. Each option will only accept an argument if that option is followed by a ":". So If you were to enter the line of code like this

while getopts "a:o:b" OPTION; #### -- note the missing ":" after the b option

any argument that you had hoped to pass along pertaining to the b would be lost. One easy way to test this out is to simple walk through each optarg section in the case and echo out what his optarg argument is.

So that's it for this week. As always if you have any questions or comments please feel free to.
contact me. Happy coding.



Monday, November 17, 2008

An introduction to Unix shell scripting.

One of the classes that I took during my post bach studies was entitled An introduction to Unix programming. Now I had worked with Unix briefly during my undergrad studies, but never really considered it as a programming language. It's an operating system right? However during the taking of the class I came to an epiphany. That epiphany being that one of the truly beautiful things about Unix is that it's a little of both. Since all the guys that developed the operating system were programmers first and foremost they built an operating system so rich in tools that the operating system itself was essentially a programmers operating system. This might explain why so many non programmers have so many frustrations with Unix, and why so many geeks find themselves right at home in it. The gentleman who taught the class was an extremely experienced C and C++ programmer and he made a statement about Unix that has stuck with me to this very day. He said "The thing I like about Unix is that everyday you work with it you find some tiny little jewel hidden in there". As I have been programming in Unix for these last 14 years I can confirm that he was exactly right. There is not a day that passes that I do not find some cool little thing that I ddn't know about, or some nifty little tool.

However, all that being said, Unix can be confusing and it's tools are all too often arcane and difficult to understand. My objective then in starting this blog was two fold. Firstly, I would like to help folks to overcome some of the many pitfalls and gotcha's that have cost me time and anguish over the years. Second, my hope is to create a reservoir for all the little code pieces so that myself and hopefully others can pull from for future efforts.