Search code examples
bashgetopts

Handle Bash getopts option with one of other options


My current Bash script looks like in the following. So far it's working except the option -g. I'd like this option to be optional but it cannot be used without any of -c or -n.

So what I mean is:

  • -g shall be completely optional
  • If, however, it is given then -c or -n must also be present.

Unfortunately I don't have any idea how to do that.

while getopts ':cniahg:' opt; do
  case $opt in
  g) DAYS_GRACE_PERIOD=$OPTARG ;;
  c) prune_containers ;;
  i) prune_images ;;
  n) prune_networks ;;
  a)
    prune_containers
    prune_networks
    prune_images
    ;;
  :) echo "Invalid option: $OPTARG requires an argument" 1>&2 ;;
  h) print_usage ;;
  \?) print_usage ;;
  *) print_usage ;;
  esac
done
shift $((OPTIND - 1))

Solution

  • -g option to be optional but it cannot be used without any of -c or -n.

    Store in a variable that option c and in another variable that option n was used and in another that option g was used. After parsing options, check the condition using the variables.

    g_used=false c_used=false n_used=false
    while .....
       g) g_used=true; ...
       c) c_used=true; ...
       n) n_used=true; ...
    ....
    
    # something like that
    if "$g_used"; then
        if ! "$c_used" || ! "$n_used"; then
          echo "ERROR: -g option was used, but -c or -n option was not used"
        fi
    fi
    
    # ex. move the execution of actions after the option parsing
    if "$c_used"; then
        prune_containers
    fi
    if "$n_used"; then
        prune_networks
    fi
    

    It looks like your loop executes action with parsing arguments. In your parsing options loop you can just set the variables associated with each option, then after the loop execute the actions depending on the "state of all options". After the loop, because then you will have a "global" view of all options used, so parsing and making decisions based on multiple flags will be easier.