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.