3

Considering:

#!/bin/sh

while getopts ":h" o; do
  case "$o" in
    h )
    "Usage:
    sh $(basename "$0") -h      Displays help message
    sh $(basename "$0") arg     Outputs ...

     where:
    -h   help option
        arg  argument."
    exit 0
    ;;
    \? )
    echo "Invalid option -$OPTARG" 1>&2
    exit 1
    ;;
    : )
    echo "Invalid option -$OPTARG requires argument" 1>&2
    exit 1
    ;;
  esac
done

This invocation returns not found why?

$ sh getopts.sh -h
getopts.sh: 12: getopts.sh: Usage:
    sh getopts.sh -h        Displays help message
    sh getopts.sh arg   Outputs ...

     where:
    -h   help option
        arg  argument.: not found

This is ok:

$ sh getopts.sh arg

For this one I was expecting 'Invalid option':

$ sh getopts.sh

This is ok:

$ sh getopts.sh -s x
Invalid option -s
5

You seemed to have missed printing the message but rather passing the whole string as a command to run. Add an echo before the string

case "$o" in
  h )
  echo "Usage:
  sh $(basename "$0") -h      Displays help message
  sh $(basename "$0") arg     Outputs ...

   where:
  -h   help option
      arg  argument."
  exit 0
  ;;

But generally prefer a style of adding a heredoc to printing out the multi-line string as

show_help() {
cat <<'EOF'
Usage:
    sh $(basename "$0") -h      Displays help message
    sh $(basename "$0") arg     Outputs ...

     where:
    -h   help option
        arg  argument.
EOF
}

and use the function show_help for the -h flag.

Also for empty argument flags, the first calls to getopts() exits the loop, so you cannot have a handle inside the loop. Have a generic check for empty arguments before invoking getopts()

if [ "$#" -eq 0 ]; then
    printf 'no argument flags provided\n' >&2
    exit 1
fi

With your earlier definition of argument flag :h, suggests that -h does not take any argument. The clause :) only applies when you define -h to take an argument i.e. when defined as :h:. Only then you run it without passing the arguments the code under :) gets executed. Putting together the whole script

#!/usr/bin/env bash

if [ "$#" -eq 0 ]; then
    printf 'no argument flags provided\n' >&2
    exit 1
fi

show_help() {
cat <<'EOF'
Usage:
    sh $(basename "$0") -h      Displays help message
    sh $(basename "$0") arg     Outputs ...

     where:
    -h   help option
        arg  argument.
EOF
}

while getopts ":h:" opt; do
  case "$opt" in
    h )
    show_help
    exit 1
    ;;
    \? )
    echo "Invalid option -$OPTARG" 1>&2
    exit 1
    ;;
    : )
    echo "Invalid option -$OPTARG requires argument" 1>&2
    exit 1
    ;;
  esac
done

and running it now

$ bash script.sh 
no argument flags provided
$ bash script.sh -h
Invalid option -h requires argument
$ bash script.sh -s
Invalid option -s
| improve this answer | |
  • 1
    Oops! Still, the no-arg invocation does not return a message. – Erwann Jun 28 '19 at 4:07
  • 1
    @Erwann: See update – Inian Jun 28 '19 at 4:14
  • The problem with the cat 'EOF' construct is that everything is printed on one line. Adding \n on each line is ignored. I invoke bash script.sh and GNU bash is version 4.4.19. – Erwann Jun 29 '19 at 18:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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