56

Is it possible to use getopts to process multiple options together? For example, myscript -iR or myscript -irv.

Also, I have a situation where based on a condition script would need mandatory option. For example, if argument to script is a directory, I will need to specify -R or -r option along with any other options (myscript -iR mydir or myscript -ir mydir or myscript -i -r mydir or myscript -i -R mydir), in case of file only -i is sufficient (myscript -i myfile).

I tried to search but didn't get any answers.

1 Answer 1

133

You can concatenate the options you provide and getopts will separate them. In your case statement you will handle each option individually.

You can set a flag when options are seen and check to make sure mandatory "options" (!) are present after the getopts loop has completed.

Here is an example:

#!/bin/bash rflag=false small_r=false big_r=false usage () { echo "How to use"; } options=':ij:rRvhm' while getopts $options option do case "$option" in i ) i_func;; j ) j_arg=$OPTARG;; r ) rflag=true; small_r=true;; R ) rflag=true; big_r=true;; v ) v_func; other_func;; h ) usage; exit;; \? ) echo "Unknown option: -$OPTARG" >&2; exit 1;; : ) echo "Missing option argument for -$OPTARG" >&2; exit 1;; * ) echo "Unimplemented option: -$option" >&2; exit 1;; esac done if ((OPTIND == 1)) then echo "No options specified" fi shift $((OPTIND - 1)) if (($# == 0)) then echo "No positional arguments specified" fi if ! $rflag && [[ -d $1 ]] then echo "-r or -R must be included when a directory is specified" >&2 exit 1 fi 

This represents a complete reference implementation of a getopts function, but is only a sketch of a larger script.

Sign up to request clarification or add additional context in comments.

8 Comments

Many thanks Dennis. I have used the flags as you suggested. I tried to simplify the logic by concatenating options and storing them in a variable and later doing processing based on the options provided.
The difference between unimplemented and unknown option is that for the former an option was supplied which matches an option character in $options, but no entry in the case statement and for the latter an option was supplied which doesn't match any character in $options.
Note that you do not have to prefix variable names with $ within arithmetic blocks; so you can just do shift $((OPTIND-1))
By the way * ) echo "Unimplemented option: -$OPTARG" >&2; exit 1;; should state -$option and not -$OPTARG otherwise it says the argument to the option is unimplemented rather than the flag is unimplemented. The original way using -$OPTARG: ` ./foo.bash -m foo Unimplemented option: -foo ` If you use -$option you get what's expected: ` ./foo -m foo Unimplemented option: -m `
@ElvenSpellmaker: I apologize. You are correct. I've edited my answer.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.