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

1 Answer 1

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
3
  • 1
    Oops! Still, the no-arg invocation does not return a message.
    – Erwann
    Jun 28, 2019 at 4:07
  • 1
    @Erwann: See update
    – Inian
    Jun 28, 2019 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, 2019 at 18:03

You must log in to answer this question.

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