I want to call myscript
file in this way:
$ ./myscript -s 45 -p any_string
or
$ ./myscript -h #should display help $ ./myscript #should display help
My requirements are:
getopt
here to get the input arguments-s
exists, if not return an error-s
is 45 or 90-p
exists and there is an input string after./myscript -h
or just ./myscript
then display helpI tried so far this code:
#!/bin/bash while getopts "h:s:" arg; do case $arg in h) echo "usage" ;; s) strength=$OPTARG echo $strength ;; esac done
But with that code I get errors. How to do it with Bash and getopt
?
On Unix-like operating systems, getopts is a builtin command of the Bash shell. It parses command options and arguments, such as those passed to a shell script. How it works. Specifying the optstring. Verbose error checking.
Description. The getopts command is a Korn/POSIX Shell built-in command that retrieves options and option-arguments from a list of parameters. An option begins with a + (plus sign) or a - (minus sign) followed by a character. An option that does not begin with either a + or a - ends the OptionString.
The main differences between getopts and getopt are as follows: getopt does not handle empty flag arguments well; getopts does. getopts is included in the Bourne shell and Bash; getopt needs to be installed separately. getopt allows for the parsing of long options ( --help instead of -h ); getopts does not.
getopt is a C library function used to parse command-line options of the Unix/POSIX style. It is a part of the POSIX specification, and is universal to Unix-like systems. It is also the name of a Unix program for parsing command line arguments in shell scripts.
#!/bin/bash usage() { echo "Usage: $0 [-s <45|90>] [-p <string>]" 1>&2; exit 1; } while getopts ":s:p:" o; do case "${o}" in s) s=${OPTARG} ((s == 45 || s == 90)) || usage ;; p) p=${OPTARG} ;; *) usage ;; esac done shift $((OPTIND-1)) if [ -z "${s}" ] || [ -z "${p}" ]; then usage fi echo "s = ${s}" echo "p = ${p}"
Example runs:
$ ./myscript.sh Usage: ./myscript.sh [-s <45|90>] [-p <string>] $ ./myscript.sh -h Usage: ./myscript.sh [-s <45|90>] [-p <string>] $ ./myscript.sh -s "" -p "" Usage: ./myscript.sh [-s <45|90>] [-p <string>] $ ./myscript.sh -s 10 -p foo Usage: ./myscript.sh [-s <45|90>] [-p <string>] $ ./myscript.sh -s 45 -p foo s = 45 p = foo $ ./myscript.sh -s 90 -p bar s = 90 p = bar
The problem with the original code is that:
h:
expects parameter where it shouldn't, so change it into just h
(without colon)-p any_string
, you need to add p:
to the argument listBasically :
after the option means it requires the argument.
The basic syntax of getopts
is (see: man bash
):
getopts OPTSTRING VARNAME [ARGS...]
where:
OPTSTRING
is string with list of expected arguments,
h
- check for option -h
without parameters; gives error on unsupported options;h:
- check for option -h
with parameter; gives errors on unsupported options;abc
- check for options -a
, -b
, -c
; gives errors on unsupported options;:abc
- check for options -a
, -b
, -c
; silences errors on unsupported options;
Notes: In other words, colon in front of options allows you handle the errors in your code. Variable will contain ?
in the case of unsupported option, :
in the case of missing value.
OPTARG
- is set to current argument value,
OPTERR
- indicates if Bash should display error messages.So the code can be:
#!/usr/bin/env bash usage() { echo "$0 usage:" && grep " .)\ #" $0; exit 0; } [ $# -eq 0 ] && usage while getopts ":hs:p:" arg; do case $arg in p) # Specify p value. echo "p is ${OPTARG}" ;; s) # Specify strength, either 45 or 90. strength=${OPTARG} [ $strength -eq 45 -o $strength -eq 90 ] \ && echo "Strength is $strength." \ || echo "Strength needs to be either 45 or 90, $strength found instead." ;; h | *) # Display help. usage exit 0 ;; esac done
Example usage:
$ ./foo.sh ./foo.sh usage: p) # Specify p value. s) # Specify strength, either 45 or 90. h | *) # Display help. $ ./foo.sh -s 123 -p any_string Strength needs to be either 45 or 90, 123 found instead. p is any_string $ ./foo.sh -s 90 -p any_string Strength is 90. p is any_string
See: Small getopts tutorial at Bash Hackers Wiki
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With