3

I need to check for user provided options in my bash script, but the options won't always be provided while calling the script. For example the possible options can be -dontbuild -donttest -dontupdate in any combination, is there a way I could check for them? Sorry if this question is real basic, I'm new to bash scripting.

Thanks

EDIT: I tried this chunk of code out, and called the script with the option, -disableVenusBld, but it still prints out "Starting build". Am I doing something wrong? Thanks in advance!

while [ $# -ne 0 ]
do
    arg="$1"
    case "$arg" in
        -disableVenusBld)
            disableVenusBld=true
            ;;
        -disableCopperBld)
            disableCopperBld=true
            ;;
        -disableTest)
            disableTest=true
            ;;
        -disableUpdate)
            disableUpdate=true
            ;;
        *)
            nothing="true"
            ;;
    esac
    shift
done

if [ "$disableVenusBld" != true ]; then
    echo "Starting build"
fi

2 Answers 2

4

Dennis had the right idea, i'd like to suggest a few minor mods.

Arguments to shell scripts are accessed by positional parameters $1, $2, $3, etc... and the current count comes in $#. The classical check for this would be:

while [ $# -ne 0 ]
do
    ARG="$1"
    shift # get rid of $1, we saved in ARG already
    case "$ARG" in
    -dontbuild)
        DONTBUILD=1
        ;;
    -somethingwithaparam)
        SAVESOMEPARAM="$1"
        shift
        ;;
# ... continue
done

As Dennis says, if your requirements fit into getopts, you're better off using that.

3
  • What purpose does doing it this way serve? It's functionally identical to the answer I gave but has an unnecessary conditional, variable assignment and shift adding extra weight. Sep 8, 2010 at 20:57
  • 1
    Dennis, you actually don't iterate through the arguments. for arg doesn't actually work in bash, you need to reference $1, $2, etc. You need the shift to actually iterate through the arguments, and the extra var ARG is to be able to use shift right away, so any params are in $1 Sep 8, 2010 at 21:13
  • 1
    for arg does an implicit iteration over $@ so it most certainly does work. Try it. You could also do it explicitly with for $arg in $@. By not using shift you can leave $@ intact. Sep 9, 2010 at 1:25
7
for arg
do
    case "$arg" in
        -dontbuild)
            do_something
            ;;
        -donttest)
            do_something
            ;;
        -dontupdate)
            do_something
            ;;
        *)
            echo "Unknown argument"
            exit 1
            ;;
     esac
done

Where do_something represents either setting a flag or actually doing something. Note that for arg implicitly iterates over $@ (the array of positional parameters) and is equivalent to the explicit for arg in $@.

Note also that Bash has a builtin called getopts but it only takes short options (e.g. -x). There's also an external utility called getopt which does take long options but it has several flaws and is not recommended.

options=":es:w:d:"

OLDOPTIND=$OPTIND
while getopts $options option
do
  case $option in
    e     ) do_something;;
    w     ) do_something $OPTARG;;
    d     ) foo=$OPTARG;;
    q     ) do_something;;
    s ) case $OPTARG in
                m | M ) bar="abc";;
                s | S ) baz="def";;
                *     ) echo "Invalid option for blah blah" 1>&2; exit;;
        esac;;
    *     ) echo "Unimplemented option chosen.";;   # DEFAULT
  esac
OLDOPTIND=$OPTIND
done
2
  • The top code section doesn't compile under #!/bin/bash: "syntax error near unexpected token `case'" May 18, 2015 at 18:53
  • @MikeBlandford: There was a missing do which I have fixed. May 18, 2015 at 19:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .