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
.

- 7,723
- 8
- 32
- 38
-
Relevant examples: https://stackoverflow.com/questions/14008125/shell-script-common-template – Anton Tarasenko Oct 22 '17 at 09:27
8 Answers
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 callinggetopts

- 238,783
- 38
- 220
- 352
-
1I'm trying this inside a function, but when I try to run the function I get this error "basename: invalid option -- 'b'". It looks like it's trying to pass "-bash" to `basename` with the leading dash. – Morgan Estes Aug 07 '13 at 15:40
-
5imside a function use `"$FUNCNAME"` not `"$0"`. Also, add `local OPTIND OPTARG` – glenn jackman Aug 07 '13 at 16:08
-
Thanks. `FUNCNAME` works. I have all my functions inside a single file, so this is perfect for extending them into something useful for others. – Morgan Estes Aug 07 '13 at 22:36
-
7@sigur, make sure you quote `"$usage"` **every** place you use it. – glenn jackman Dec 24 '16 at 15:10
-
5
-
2That will remove all the options from the positional parameters, so that $1 will be the first argument that follows the options. If you were writing a function for `ls`, and you typed `ls -l -a /` then $1 would be `/` – glenn jackman Jul 22 '19 at 18:18
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.

- 3,646
- 26
- 21
-
You should make a habit of wrapping the if in [[ ... ]] for conditionals to avoid a bad parsing of a variable, source: https://github.com/bahamas10/bash-style-guide#bashisms – JREAM Mar 19 '17 at 15:38
-
3Yes, although the OP didn't specify bash, and `[` is the POSIX-compliant version. – seb Mar 20 '17 at 16:16
-
1**Note - For using inside `function`:** You should replace `exit 0` with `return` if you don't want to terminate your shell after run your function. (I've done it before ) – Illuminator Sep 07 '17 at 16:19
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

- 594
- 1
- 9
- 26

- 543
- 4
- 7
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.

- 7,605
- 2
- 68
- 92
-
Thanks! I have been happily using getopts for a year now, but I'll have a look at getopt too. – tttppp Mar 01 '13 at 11:57
-
3Sadly, the link to The 60 Second getopts Tutorial is dead; it seems that bashcurescancer.com is no more. Here's a link to the [Wayback Machine's version](https://web.archive.org/web/20120409221849/http://bashcurescancer.com/the-60-second-getopts-tutorial.html). – jeffbyrnes Mar 12 '14 at 19:33
-
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

- 693
- 1
- 10
- 12
-
Great ! the simplest answer I found on stackoverflow, allows to custom your params easily. Thanks – Vincent Decaux Oct 29 '21 at 09:13
Better to use getopt facility of bash. Please look at this Q&A for more help: Using getopts in bash shell script to get long and short command line options
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.
$ _

- 874
- 8
- 15
i think you can use case for this...
case $1 in
-h) echo $usage ;;
h) echo $usage ;;
help) echo $usage ;;
esac

- 11