3

So I am writing a script that mixes options with arguments with options that don't. From research I have found that getopts is the best way to do this, and so far it has been simple to figure out and setup. The problem I am having is figuring out how to set this up so that if no options or arguments are supplied, for it to run a separate set of commands. This is what I have:

while getopts ":n:h" opt; do
  case $opt in
    n)
      CODEBLOCK >&2
      ;;
    h)
      echo "script [-h - help] [-n <node> - runs commands on specified node]" >&2
      exit 1
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

I have tried adding something like this to the top of the code to catch no arguments, but it then runs the same code even when options and arguments are supplied (something is probably wrong in my syntax here):

[[ -n "$1" ]] || {
CODEBLOCK1
}

while getopts ":n:h" opt; do
  case $opt in
    n)
      CODEBLOCK2 >&2
      ;;
    h)
      echo "script [-h - help] [-n <node> - runs commands on specified node]" >&2
      exit 1
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

The man page for getopts was sparse and I have found relatively few examples on searches that provide any insight into getopts, let alone all the various features of it.

0

1 Answer 1

3

You can use any of the following to run commands when $1 is empty:

[[ ! $1 ]] && { COMMANDS; }
[[ $1 ]] || { COMMANDS; }
[[ -z $1 ]] && { COMMANDS; }
[[ -n $1 ]] || { COMMANDS; }

Also, you don't need to quote the expansion in this particular example, as no word splitting is performed.

If you're wanting to check if there are arguments, though, you'd be better to use (( $# )).

If I've understood your intentions, here is how your code could be written with getopts:

#!/bin/bash

(( $# )) || printf '%s\n' 'No arguments'

while getopts ':n:h' opt; do
    case "$opt" in
        n)
            [[ $OPTARG ]] && printf '%s\n' "Commands were run, option $OPTARG, so let's do what that says."
            [[ ! $OPTARG ]] && printf '%s\n' "Commands were run, there was no option, so let's run some stuff."
            ;;
        h) printf '%s\n' 'Help printed' ;;
        *) printf '%s\n' "I don't know what that argument is!" ;;
    esac
done
9
  • Using -n or -z has the same effect. Whether I type ./script or ./script -n 3, the same codeblock is executed and everything in the getopts loop is ignored.
    – MaQleod
    Commented Sep 15, 2011 at 16:37
  • That's simply not possible -- -z will evaluate to true if $1 is empty. What is the smallest code sample that demonstrates the issue that you are having directly?
    – Chris Down
    Commented Sep 15, 2011 at 16:40
  • I did paste it wrong, in the script I'm running I have it set differently, I corrected that in the question, but I am not having problems with the getopts loop. I updated with an example, and it is probably something in my syntax that is keeping it from working properly. I tried all the different options you posted in your answer and all failed to work properly.
    – MaQleod
    Commented Sep 15, 2011 at 16:54
  • The above code should show you how to implement checking for situations where there are either a.) no arguments, or b.) arguments without an option.
    – Chris Down
    Commented Sep 15, 2011 at 17:01
  • 1
    If you are using zsh, please do not push bash in your tags in future. They are not the same.
    – Chris Down
    Commented Sep 15, 2011 at 17:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .