I was starting to understand getopts
when it just stopped running all together. When I try getopts
in small individual tests it works perfectly. I have been staring at my screen for a couple days now checking what's wrong, I even used a shellchecker which just said everything should work. I tried to echo inside the getopts
while loop and it never printed, much less the echo's I had in the cases. Here is essentially what my code is,
helpmenu(){
case $1 in
general)
echo "Usage, some operationtypes, -h or --help idenifier explained"
;;
eachoperationtype)
echo "Explain this operationtype"
;;
}
operationtype=$1
if [[ operationtype == "Operation1" ]]; then
# Setting some variables to default values here
var1=0 #Default values
var2=4
var3=5
...
echo "this prints" # this prints
while getopts ":hs:d:m:f:a" opt; do
echo "does not print" # this does not print
case ${opt} in
h )
helpmenu operationtype #Simple function that prints out script usage
;;
s )
var=$OPTARG
;;
d )
var2=$OPTARG
;;
m )
var3=$OPTARG
;;
f )
var4=$OPTARG
;;
a )
bool=true
;;
\? )
echo "Syntax error: Unrecognised flags given"
helpmenu operationtype
;;
: )
echo "Syntax error: Invalid number of arguments"
helpmenu general # No arguments given - shows help menu with operationtypes so they can ./Script operationtype -h
;;
esac
done
shift $((OPTIND -1))
# Do some other stuff, works fine
#Other operations have similar structure to operationtype1
elif [[ operationtype == "operation2" ]]; then
# Similar program, potentially different flags, function, meaning etc
fi
The main point of the script is to take in an initial first argument that is the type of operation that is required, and to run different getopts
in different elifs
after the initial if
. Each one would have a specific amount of arguments that it accepted along with a list of optional flags. i.e. you could have one script that does ./Script greetings "hello" -t 3
which could for example echo "hello"
3 times and have another function in the same script./Script age -u User1
that gives the age of user1 in a list for example. Another issue that I am dealing with is the setting of the required variables, the required variables should just be normally gathered without flags. The issue with this is I want a help menu to pop up (echo out a quick usage) for each operationtype - i.e. ./Script operation1 -h
returns operation1's help menu however I cannot allow this syntax as it will return an error when trying to set the required arguments. Also I need to make sure that they putting exactly the right amount of required args for each operationtype as any other amount will cause an error. Thanks for any help in advance.
Edit:
I have checked my code with shellcheck.net, and I believe that there are no syntax based mistakes. I need help not really with the specifics of the code but rather what the best way to achieve the result I want, with the rough idea that I have highlighted above. Is this the best way to go about this? How would I get the operationtype
based helpmenu
functionality? And why isn't getopts
running? Sorry for any confusion, I shall remove the pastebin link as making you read through it was not my intention at all.
The main difference between the ASK in the question and the 'traditional' usage of getopt is that the command line arguments follows the structure
script sub-command [options] arguments
Where the 'traditional' use case for getopt expects the following (and the command may be implied from the options, or be part of the argument list).
script [options] arguments
Small minor changes are needed here, hinting to getopt that the first command line arguments should be ignored. Two options: shift the argument list, or update the OPTIND to skip those arguments
# SHIFT the command outside the argument list
operationtype=$1
shift
if [[ operationtype == "Operation1" ]]; then
# Execute the operation 1
...
while getopts ":hs:d:m:f:a" opt; do
...
done
Or updating OPTIND to skip 1 the first argument.
operationtype=$1
OPTIND=$((OPTIND+1))
if [[ operationtype == "Operation1" ]]; then
# Execute the operation 1
...
while getopts ":hs:d:m:f:a" opt; do
...
done
Note: Each of those solution can be used to provide 2 sets of options. One for the script, and one for the sub-command. For example, the docker
command line:
docker [options] sub-command [sub-command options]
Original Answer:
Completely revised to to address changes made by the OP.