How to run a specified codeblock with getopts when no options or arguments are supplied?
You can use any of the following to run commands when $1
is empty:
[[ ! $1 ]] && { COMMANDS; }
[[ $1 ]] || { COMMANDS; }
[[ -z $1 ]] && { COMMANDS; }
[[ -n $1 ]] || { COMMANDS; }
Also, you don't need to quote the expansion in this particular example, as no word splitting is performed.
If you're wanting to check if there are arguments, though, you'd be better to use (( $# ))
.
If I've understood your intentions, here is how your code could be written with getopts
:
#!/bin/bash
(( $# )) || printf '%s\n' 'No arguments'
while getopts ':n:h' opt; do
case "$opt" in
n)
[[ $OPTARG ]] && printf '%s\n' "Commands were run, option $OPTARG, so let's do what that says."
[[ ! $OPTARG ]] && printf '%s\n' "Commands were run, there was no option, so let's run some stuff."
;;
h) printf '%s\n' 'Help printed' ;;
*) printf '%s\n' "I don't know what that argument is!" ;;
esac
done
Related videos on Youtube
MaQleod
I'm a Software Quality Principal Engineer that specializes in Networking and hardware (with a strong emphasis on Unix/Linux systems). My background is in Telecom and Network troubleshooting. I am proficient in both Ethernet and Infiniband standards. I code primarily with Python, Autoit, C and and SQL in my spare time, but I like to occasionally tinker in other languages. My degree is in Classical Numismatics and Archaeology. I also keep a blog on investing. profile for MaQleod on Stack Exchange, a network of free, community-driven Q&A sites http://stackexchange.com/users/flair/343e8ac1ebe84dacb26151af03317dcd.png
Updated on September 18, 2022Comments
-
MaQleod almost 2 years
So I am writing a script that mixes options with arguments with options that don't. From research I have found that getopts is the best way to do this, and so far it has been simple to figure out and setup. The problem I am having is figuring out how to set this up so that if no options or arguments are supplied, for it to run a separate set of commands. This is what I have:
while getopts ":n:h" opt; do case $opt in n) CODEBLOCK >&2 ;; h) echo "script [-h - help] [-n <node> - runs commands on specified node]" >&2 exit 1 ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done
I have tried adding something like this to the top of the code to catch no arguments, but it then runs the same code even when options and arguments are supplied (something is probably wrong in my syntax here):
[[ -n "$1" ]] || { CODEBLOCK1 } while getopts ":n:h" opt; do case $opt in n) CODEBLOCK2 >&2 ;; h) echo "script [-h - help] [-n <node> - runs commands on specified node]" >&2 exit 1 ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done
The man page for getopts was sparse and I have found relatively few examples on searches that provide any insight into getopts, let alone all the various features of it.
-
MaQleod almost 13 yearsUsing -n or -z has the same effect. Whether I type ./script or ./script -n 3, the same codeblock is executed and everything in the getopts loop is ignored.
-
clerksx almost 13 yearsThat's simply not possible --
-z
will evaluate to true if$1
is empty. What is the smallest code sample that demonstrates the issue that you are having directly? -
MaQleod almost 13 yearsI did paste it wrong, in the script I'm running I have it set differently, I corrected that in the question, but I am not having problems with the getopts loop. I updated with an example, and it is probably something in my syntax that is keeping it from working properly. I tried all the different options you posted in your answer and all failed to work properly.
-
clerksx almost 13 yearsThe above code should show you how to implement checking for situations where there are either a.) no arguments, or b.) arguments without an option.
-
MaQleod almost 13 yearsNo matter how I do it, whether an option is provided or not, the code runs CODEBLOCK1. The only variance is with the first option [[ ! $1 ]] && { COMMANDS; } , it runs CODEBLOCK2 as expected, but will not ever run CODEBLOCK1, it produces an error: [[: not found. I even tested it with (( $# )) || and had the same as the majority of the others.
-
clerksx almost 13 years
[[: not found
indicates that you are not runningbash
, or you are running it as#!/bin/sh
. sh is the POSIX or Bourne shell, notbash
. Even ifsh
is a symlink tobash
, running a script undersh
(either by typingsh myscript
or putting#!/bin/sh
at the top) disables many bash features. You can either use[
instead (make sure to quote any expansions), or runbash
in non-POSIX mode. -
MaQleod almost 13 yearsit is zsh, but I can't change that, I can't change anything with the system, only the script. I am running it with #!/bin/sh. Even if I use a [ and quote the expansion I have the same results.
-
MaQleod almost 13 yearsOk, so single brackets did the trick.
-
clerksx almost 13 yearsIf you are using
zsh
, please do not pushbash
in your tags in future. They are not the same.