Consuming Arguments

Problem

For any serious shell script, you are likely to have two kinds of arguments—options that modify the behavior of the script and the real arguments with which you want to work. You need a way to get rid of the option argument(s) after you’ve processed them.

Remember this script:

for FN in "$@"
do
    echo changing $FN
    chmod 0750 "$FN"
done

It’s simple enough—it echoes the filename that it is working on, then it changes that file’s permissions. What if you want it to work quietly sometimes, not echoing the filename? How would we add an option to turn off this verbose behavior while preserving the for loop?

Solution

#!/usr/bin/env bash
# cookbook filename: use_up_option
#
# use and consume an option
#
# parse the optional argument
VERBOSE=0;
if [[ $1 = -v ]]
then
    VERBOSE=1;
    shift;
fi
#
# the real work is here
#
for FN in "$@"
do
    if (( VERBOSE == 1 ))
    then
        echo changing $FN
    fi
    chmod 0750 "$FN"
done

Discussion

We add a flag variable, $VERBOSE, to tell us whether or not to echo the filename as we work. But once the shell script has seen the -v and set the flag, we don’t want the -v in the argument list any more. The shift statement tells bash to shift its arguments down one position, getting rid of the first argument ($1) as $2 becomes $1, and $3 becomes $2, and so on.

That way, when the for loop runs, the list of parameters (in $@) no longer contains the -v but starts with the next parameter.

This approach of parsing arguments is alright for handling a single option. But ...

Get bash Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.