How can I add a help method to a shell script?

UnixShell

Unix Problem Overview


How do I check if a -h attribute has been passed into a shell script? I would like to display a help message when a user calls myscript.sh -h.

Unix Solutions


Solution 1 - Unix

here's an example for bash:

usage="$(basename "$0") [-h] [-s n] -- program to calculate the answer to life, the universe and everything

where:
    -h  show this help text
    -s  set the seed value (default: 42)"

seed=42
while getopts ':hs:' option; do
  case "$option" in
    h) echo "$usage"
       exit
       ;;
    s) seed=$OPTARG
       ;;
    :) printf "missing argument for -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
   \?) printf "illegal option: -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
  esac
done
shift $((OPTIND - 1))

To use this inside a function:

  • use "$FUNCNAME" instead of $(basename "$0")
  • add local OPTIND OPTARG before calling getopts

Solution 2 - Unix

The first argument to a shell script is available as the variable $1, so the simplest implementation would be

if [ "$1" == "-h" ]; then
  echo "Usage: `basename $0` [somestuff]"
  exit 0
fi

But what anubhava said.

Solution 3 - Unix

here is a part I use it to start a VNC server

#!/bin/bash
start() {
echo "Starting vnc server with $resolution on Display $display"
#your execute command here mine is below
#vncserver :$display -geometry $resolution
}

stop() {
echo "Killing vncserver on display $display"
#vncserver -kill :$display
}

#########################
# The command line help #
#########################
display_help() {
    echo "Usage: $0 [option...] {start|stop|restart}" >&2
    echo
    echo "   -r, --resolution           run with the given resolution WxH"
    echo "   -d, --display              Set on which display to host on "
    echo
    # echo some stuff here for the -a or --add-options 
    exit 1
}

################################
# Check if parameters options  #
# are given on the commandline #
################################
while :
do
    case "$1" in
      -r | --resolution)
          if [ $# -ne 0 ]; then
            resolution="$2"   # You may want to check validity of $2
          fi
          shift 2
          ;;
      -h | --help)
          display_help  # Call your function
          exit 0
          ;;
      -d | --display)
          display="$2"
           shift 2
           ;;

      -a | --add-options)
          # do something here call function
          # and write it in your help function display_help()
           shift 2
           ;;

      --) # End of all options
          shift
          break
          ;;
      -*)
          echo "Error: Unknown option: $1" >&2
          ## or call function display_help
          exit 1 
          ;;
      *)  # No more options
          break
          ;;
    esac
done

###################### 
# Check if parameter #
# is set too execute #
######################
case "$1" in
  start)
    start # calling function start()
    ;;
  stop)
    stop # calling function stop()
    ;;
  restart)
    stop  # calling function stop()
    start # calling function start()
    ;;
  *)
#    echo "Usage: $0 {start|stop|restart}" >&2
     display_help

     exit 1
     ;;
esac

It's a bit weird that I placed the start stop restart in a separate case but it should work

Solution 4 - Unix

For a quick single option solution, use if

If you only have a single option to check and it will always be the first option ($1) then the simplest solution is an if with a test ([). For example:

if [ "$1" == "-h" ] ; then
    echo "Usage: `basename $0` [-h]"
    exit 0
fi

Note that for posix compatibility = will work as well as ==.

Why quote $1?

The reason the $1 needs to be enclosed in quotes is that if there is no $1 then the shell will try to run if [ == "-h" ] and fail because == has only been given a single argument when it was expecting two:

$ [ == "-h" ]
bash: [: ==: unary operator expected

For anything more complex use getopt or getopts

As suggested by others, if you have more than a single simple option, or need your option to accept an argument, then you should definitely go for the extra complexity of using getopts.

As a quick reference, I like The 60 second getopts tutorial.

You may also want to consider the getopt program instead of the built in shell getopts. It allows the use of long options, and options after non option arguments (e.g. foo a b c --verbose rather than just foo -v a b c). This Stackoverflow answer explains how to use GNU getopt.

jeffbyrnes mentioned that the original link died but thankfully the way back machine had archived it.

Solution 5 - Unix

Solution 6 - Unix

There's a simple way to implement this without getopt or getopts:

display_help() {
    # taken from https://stackoverflow.com/users/4307337/vincent-stans
    echo "Usage: $0 [option...] {start|stop|restart}" >&2
    echo
    echo "   -r, --resolution           run with the given resolution WxH"
    echo "   -d, --display              Set on which display to host on "
    echo
    # echo some stuff here for the -a or --add-options 
    exit 1
}

log() {
    echo "This is a log"
}
while [[ "$#" -gt 0 ]]; do
    case $1 in
        -h|--help) display_help; shift ;;
        -l|--log) log; shift ;;
        # ... (same format for other required arguments)
        *) echo "Unknown parameter passed: $1" ;;
    esac
    shift
done

Solution 7 - Unix

Here's a super-compact, yet readable way to add basic help based on @zeb's version. It handles both of the commonly used -h and --help flags.

[ "$1" = "-h" -o "$1" = "--help" ] && echo "
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
  incididunt ut labore et dolore magna aliqua.

  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
  aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
  voluptate velit esse cillum dolore eu fugiat nulla pariatur.
" && exit

The result looks like this:

$ ./myscript.sh -h

  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
  incididunt ut labore et dolore magna aliqua.

  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
  aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
  voluptate velit esse cillum dolore eu fugiat nulla pariatur.

$ _

Solution 8 - Unix

i think you can use case for this...

case $1 in 
 -h) echo $usage ;; 
  h) echo $usage ;;
help) echo $usage ;;
esac

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontttpppView Question on Stackoverflow
Solution 1 - Unixglenn jackmanView Answer on Stackoverflow
Solution 2 - UnixsebView Answer on Stackoverflow
Solution 3 - UnixVincent StansView Answer on Stackoverflow
Solution 4 - UnixMark BoothView Answer on Stackoverflow
Solution 5 - UnixanubhavaView Answer on Stackoverflow
Solution 6 - UnixEge HurturkView Answer on Stackoverflow
Solution 7 - Unixapostl3polView Answer on Stackoverflow
Solution 8 - Unixnew userView Answer on Stackoverflow