I have searched a couple of days and still didn't found the answer. I hope that you can point me in right direction.

I would like to know how to write a bash script with a options, that can be called in one row, such as: script.sh -a -b -c. Parameters which aren't chosen are ignored.

Menu/options should be like:

-a description: something
-b description: something else
-c description: something different
-d description: something..

is there any way to do this?


The usual way of handling switches and arguments is with the getopts function. In bash this is a builtin and you can find information about it in the bash man page (man bash).

Essentially, you declare a string that tells getopts what parameters to expect, and whether they should have an argument. It's getopts that handles bunched parameters (eg -abc being equivalent to -a -b -c) and the parsing of the command line. At the end of the getopts processing you have the remainder of the command line to handle as you see fit.

A typical script segment could look something like this

while getopts 'a:bc' OPT    # -a {argument}, -b, -c
    case "$OPT" in
        a)    ARG_A="$OPTARG" ;;
        b)    FLAG_B=yes ;;
        c)    FLAG_C=yes ;;
        *)    echo "ERROR: the options are -a {arg}, -b, -c" >&2; exit 1 ;;
shift $(($OPTIND - 1))

echo "Remaining command line: $*"

You can add ? as a command option if you want a nice usage message. Remember that in the case block you would need to quote it or prefix it with a backslash so it's treated as a literal.

If you're wanting to run this under a different shell that doesn't have the builtin, or if you want to use long arguments such as --verbose instead of just -v take a look at the getopt utility. This is not a builtin but has been written to deliver in the more sophisticated situation.

| improve this answer | |

You don't have to use any Bash-specific features to do this:

while true
    case "$1" in
        -a)  echo Saw -a!  ;;
        -b)  echo Saw -b!  ;;
        -c)  echo Saw -c!  ;;
        -?)  cat <<USAGE
usage: $0 [-a] [-b] [-c] args

    You cannot currently combine options, as with -ac.
            exit 1
            echo End of options!

    shift       # toss current $1; we're done with it now

for p in "$@"
    echo "Non-option argument: '$p'"

Unlike the code in roaima's answer, mine is portable shell script code. It will run on any Bourne type Unix shell going back to about 1980 or so.

I think the -? handler answers your "menu" requirement. The <<USAGE construct is called a heredoc.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.