Chris Jones wrote: > How do I handle mutually exclusive flags with getopts?
Not seeing any other answers I might as well chime in. I usually use the 'getopt' way and not the 'getopts' way, because I have always used getopt. And the GNU version handles long options (--long-opt). GNU standards require long options along with --version and --help and that pushes me to getopt. But with getopts you should find this reference is useful: http://www.opengroup.org/onlinepubs/009695399/utilities/getopts.html > But I'd like to be able to run it manually and specify via flags the > backup I want to run - daily/incremental or monthly/full. > > $ backup -d # daily backup > $ backup -m # monthly .. Sure. > So far my best effort still finds the following acceptable: > > $ backup -dm > > I'm trying to use getopts to implement an exclusive OR of the two > options. As far as I know with all of the option parsing routines available you would need to code this type of validation in yourself. The combinatorial explosion of combinations of valid and invalid options are not something that option parsing libraries can handle. Therefore you need to check for validity after the options have been read. > Incidentally, I am also curious of the "getopts" way to handle the > absence of _any_ flags. Again, AFAIK you would need to handle this in your code. Here is a quick example of the way that I normally do these types of things in my scripts. I am cutting and pasting and may make a typo here though so it would all need to be tested. I probably should turn this more into a distributable example. But hopefully it will be useful as it is regardless. #!/bin/sh # Short summary description of your program. # Copyright 2008 Bob Proulx <[EMAIL PROTECTED]> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # Longer description here as needed. # # Examples: # # progname arg1 # progname --verbose arg1 arg2 progname=$(basename $0) [EMAIL PROTECTED]@ print_usage() { # This script is designed to use help2man to build the man page # directly from the script itself. # help2man programname # Check the man page formatting after making changes here. cat <<'EOF' Description of script goes here. This is both your man page when run through help2man and your online help. Document your program here. Usage: programname [options] Options: -v, --verbose verbose operation -n, --dry-run not really, just print what would be done --help print this help message --version print program version Examples: $ programname --help $ programname --verbose --dry-run $ programname arg1 arg2 Report bugs to <[EMAIL PROTECTED]>. EOF } print_version() { echo "$progname $version" echo "Copyright (C) 2008 Your Name <[EMAIL PROTECTED]>." echo "License GPLv3+: GNU GPL version 3 or later" echo "<http://gnu.org/licenses/gpl.html>" echo "This is free software: you are free to change and redistribute it." echo "There is NO WARRANTY, to the extent permitted by law." echo "" echo "Written by Your Name <[EMAIL PROTECTED]>." } SHORTOPTS="dmnv" LONGOPTS="daily,monthly,help,verbose,version" if $(getopt -T >/dev/null 2>&1) ; [ $? = 4 ] ; then # New longopts getopt. OPTS=$(getopt -o $SHORTOPTS --long $LONGOPTS -n "$progname" -- "$@") else # Old classic getopt. # Special handling for --help and --version on old getopt. case $1 in --help) print_usage ; exit 0 ;; esac case $1 in --version) print_version ; exit 0 ;; esac OPTS=$(getopt $SHORTOPTS "$@") fi if [ $? -ne 0 ]; then echo "'$progname --help' for more information" 1>&2 exit 1 fi eval set -- "$OPTS" daily=false monthly=false verbose=false while [ $# -gt 0 ]; do : debug: $1 case $1 in -d|--daily) daily=true shift ;; -m|--monthly) monthly=true shift ;; --help) print_usage exit 0 ;; -n|--dry-run) notreally=true shift ;; --quiet) quiet=true shift ;; -v|--verbose) verbose=true shift ;; --version) print_version exit 0 ;; --) shift break ;; *) echo "Internal Error: option processing error: $1" 1>&2 exit 1 ;; esac done if $daily && $monthly; then echo "Error: Both daily (-d) and monthly (-m) were specified." 1>&2 exit 1 fi if ! $daily && ! $monthly; then echo "Error: Neither daily (-d) nor monthly (-m) were specified." 1>&2 exit 1 fi $verbose && echo "Processing..." if $daily; then echo "Doing daily stuff..." fi if $monthly; then echo "Doing monthly stuff..." fi exit 0 Hope this helps, Bob