getopts Using arguments and parameters

Writing complex scripts, will require that you provide your scripts with parameters. The more complex the scripts, the more time you will devote in your script merely to handling the parameters.

With our eatout.sh script, we started by being able to give it a single parameter, but after some thought, we may need another, then another, and so on.

./eatout.sh <type>
            

becomes:

./eatout.sh -t <type>
            

then

	./eatout.sh -t <type> -r <rating>
            

where

-t for the type of restaurant
and 
-r for the rating 
            

We may want to use them in any order too:

./eatout.sh -t Italian -r 8
            

or

./eatoutput -r 8 -t italian
            

If you give a moments thought to coding all these options into the shell you will find that things become a lot more complex. In fact, dealing with the arguments could even become more complex than the entire rest of your shell script!

For example, perhaps you had 3 parameters: a, i and r. Looking at the combinations, you could run the script with any of the following:

./eatout.sh -a -i -r <param>

./eatout.sh -ai -r <param>

./eatout.sh -air <param>

./eatout.sh -r <param> -ai
            

You can see that the more parameters we want to put on the command line, the more options we need to deal with.

The shell is clever and it's got a function called getopts, which is used for getting options from the command line. getopts returns a true or a false depending on whether the parameter is supplied on the command line. It's got two additional "appendages": optind and optarg.

How do we use our getopts? Well if we look at our eatout.sh script, we can see that we have two parameters with an argument for each parameter. Using a while loop we need to get every argument on the command line:

while getopts t:r: myoption
            

This will look for any option (beginning with a minus sign). getopts is expecting two options, one beginning with a t, the other beginning with an r. The colon indicates that getopts is expecting an argument for each parameter. In this case we're expecting an argument for both the t and the r parameters.

So now we could include the following loop in our script to handle our options:

while getopts t:r: MYOPTION
do
	case MYOPTION in
		t)	RESTAURANTTYPE=$OPTARG ;;
		r) 	RATING=$$OPTARG ;;
		\?) 	echo "Sorry no such option, please try again"
			exit 1
			;;
			
done
            

We're telling our script to check the parameters. If the option was a t, then it stores the argument in the RESTAURANTTYPE variable. If the option was an r, then we want to store the argument in the RATING variable. Anything else, getopts will return a question mark. If we were to put a -p on the command line where it shouldn't appear, getops will set MYOPTION to be a question mark, but remember the "?" is a wildcard character so you need to escape it.

Now we've got a very simple way of handling any number of arguments on the command line. OPTIND tells us what index on the command line we're currently handling. It starts at 1, so if we were to run the script with:

./eatout.sh -t italian	-r 5
	     1  2        3 4		#OPTIND number
            

This tells us at what options our indexes are. So what we're going to do is we're going to start building up a nice little menu-system for our users for deciding what restaurants they're going to eat at.

Where they can put a -t for the type of restaurant and a -r for the rating. What we might want to do is we might want to set a rating at the top of our script, so that if the user does not provide a rating, our script will use the default value.

Similarly, we might want to provide a default restaurant type so that if they don't give a type a particular value will be set.

Exercises:

  1. Modify your eatout.sh script to handle the parameters as described above.Modify your eatout.sh script to be able to output the results in HTML format rather than in simple text.

  2. Write a script that will take two optional parameters (a -m and a -d). When run with a -m it should produce memory statistics, while the -d should produce disk space statistics. An additional parameter should be included this time called -h. When called with the -h option, the script should create html output. The -h option should be followed by a file name (index.html or something similar) where the HTML output should be written.

  3. Write a script that will display the gif's in random order in an HTML table. The script should take two optional parameters which will

    1. -r display the GIFs in RANDOM order

    2. -o display the gifs in alphabetic order

    3. -o size display the GIFs in order by size rather than alphabetic.