3

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?

    2 Answers 2

    7

    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

    ARG_A= FLAG_B= FLAG_C= while getopts 'a:bc' OPT # -a {argument}, -b, -c do 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 ;; esac done 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.

      1

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

      #!/bin/sh while true do 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. USAGE exit 1 ;; *) echo End of options! break; ;; esac shift # toss current $1; we're done with it now done for p in "$@" do echo "Non-option argument: '$p'" done 

      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.

        You must log in to answer this question.

        Start asking to get answers

        Find the answer to your question by asking.

        Ask question

        Explore related questions

        See similar questions with these tags.