Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

share|improve this question

1 Answer 1

up vote 3 down vote accepted

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
share|improve this answer
    
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 Sep 15 '11 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 Sep 15 '11 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 Sep 15 '11 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 Sep 15 '11 at 17:01
    
No matter how I do it, whether an option is provided or not, the code runs CODEBLOCK1. The only variance is with the first option [[ ! $1 ]] && { COMMANDS; } , it runs CODEBLOCK2 as expected, but will not ever run CODEBLOCK1, it produces an error: [[: not found. I even tested it with (( $# )) || and had the same as the majority of the others. –  MaQleod Sep 15 '11 at 17:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.