Maybe something like this?
#!/bin/bash
unset -v host
unset -v port
unset -v user
while getopts h:p:u: opt; do
case $opt in
h) host=$OPTARG ;;
p) port=$OPTARG ;;
u) user=$OPTARG ;;
*)
echo 'Error in command line parsing' >&2
exit 1
esac
done
shift "$(( OPTIND - 1 ))"
if [ -z "$host" ] || [ -z "$user" ]; then
echo 'Missing -h or -u' >&2
exit 1
fi
# The rest of the script continues here and may make use of
# "$host" and "$user", and possibly "$port".
The main bit here is the short if
statement at the end that tests whether there were ever anything assigned to the host
or user
variables in the while
loop. If either of these variables are empty, then the code treats it as an error and exits after outputting a short diagnostic message.
The script shown above should also be able to run under /bin/sh
as it does not contain any bashishms.
Instead of the if
statement, you could use
: ${host:?Missing -h}
: ${user:?Missing -u}
or, even shorter,
: ${host:?Missing -h} ${user:?Missing -u}
The :
command is a utility that doesn't do anything, but its argument would still be processed by the calling shell, like for all commands. With the two lines above, the shell would try to expand the host
and user
variables, and if the variable is unset, or if the expansion results in an empty string, then the string to the right after ?
will be outputted and the script will terminate with a non-zero exit status:
$ bash script.sh -h somehost
script.sh: line 21: user: Missing -u
$ echo $?
1
The ${variable:?text}
expansion is standard and therefore supported by bash
and all other POSIX sh
-like shells.