Getopts not properly parsing arguments - bash

I have following shell script -
while getopts “h:f:p:u” OPTION
do
case $OPTION in
h)
usage
exit 1
;;
f)
FILE=$OPTARG
;;
u)
US=$OPTARG
;;
p)
PASSWD=$OPTARG
;;
?)
usage
exit
;;
esac
done
echo "$FILE"
echo "$PASSWD"
echo "$US"
I use following commandline arguments -
-u root -f mydb -p h2
There is no output on screen. Why?

Your call to getopt should look like this ...
while getopts “hf:p:u:” OPTION
... because h takes no args and the other options do.

It should be while getopts “hf:p:u:” OPTION

Related

Update parameter with default value in a bash script [duplicate]

I'm trying to make a getopt command such that when I pass the "-ab" parameter to a script,
that script will treat -ab as a single parameter.
#!/bin/sh
args=`getopt "ab":fc:d $*`
set -- $args
for i in $args
do
case "$i" in
-ab) shift;echo "You typed ab $1.";shift;;
-c) shift;echo "You typed a c $1";shift;;
esac
done
However, this does not seem to work. Can anyone offer any assistance?
getopt doesn't support what you are looking for. You can either use single-letter (-a) or long options (--long). Something like -ab is treated the same way as -a b: as option a with argument b. Note that long options are prefixed by two dashes.
i was struggling with this for long - then i got into reading about getopt and getopts
single char options and long options .
I had similar requirement where i needed to have number of multichar input arguments.
so , i came up with this - it worked in my case - hope this helps you
function show_help {
echo "usage: $BASH_SOURCE --input1 <input1> --input2 <input2> --input3 <input3>"
echo " --input1 - is input 1 ."
echo " --input2 - is input 2 ."
echo " --input3 - is input 3 ."
}
# Read command line options
ARGUMENT_LIST=(
"input1"
"input2"
"input3"
)
# read arguments
opts=$(getopt \
--longoptions "$(printf "%s:," "${ARGUMENT_LIST[#]}")" \
--name "$(basename "$0")" \
--options "" \
-- "$#"
)
echo $opts
eval set --$opts
while true; do
case "$1" in
h)
show_help
exit 0
;;
--input1)
shift
empId=$1
;;
--input2)
shift
fromDate=$1
;;
--input3)
shift
toDate=$1
;;
--)
shift
break
;;
esac
shift
done
Note - I have added help function as per my requirement, you can remove it if not needed
That's not the unix way, though some do it e.g. java -cp classpath.
Hack: instead of -ab arg, have -b arg and a dummy option -a.
That way, -ab arg does what you want. (-b arg will too; hopefully that's not a bug, but a shortcut feature...).
The only change is your line:
-ab) shift;echo "You typed ab $1.";shift;;
becomes
-b) shift;echo "You typed ab $1.";shift;;
GNU getopt have --alternative option
-a, --alternative
Allow long options to start with a single '-'.
Example:
#!/usr/bin/env bash
SOPT='a:b'
LOPT='ab:'
OPTS=$(getopt -q -a \
--options ${SOPT} \
--longoptions ${LOPT} \
--name "$(basename "$0")" \
-- "$#"
)
if [[ $? > 0 ]]; then
exit 2
fi
A=
B=false
AB=
eval set -- $OPTS
while [[ $# > 0 ]]; do
case ${1} in
-a) A=$2 && shift ;;
-b) B=true ;;
--ab) AB=$2 && shift ;;
--) ;;
*) ;;
esac
shift
done
printf "Params:\n A=%s\n B=%s\n AB=%s\n" "${A}" "${B}" "${AB}"
$ ./test.sh -a aaa -b -ab=test
Params:
A=aaa
B=true
AB=test
getopt supports long format. You can search SO for such examples.
See here, for example

Issues storing arguments from getopts in shell script

I am new using unix and I recently tried to create a code that would take some arguments and pass it to a python script and later use those arguments for downstream processes.
I am trying to use getopts but after I tried running the script it looks like my arguments were not stored in variables and anything downstream failed.
This is a piece of what I tried so far
#!/bin/bash
function usage() {
cat <<USAGE
Usage: $0 [-f fasta] [-o output name] [-m memory] [-t time] [-n number of tasks] [-c cores] [-g gpus] [-e extra]
Options:
-f fasta file
-o output name
-m memory to request
-t time to request
-n number of tasks
-c cores to request
-g gpus to request - no more than 4!
-e extra arguments for program
USAGE
}
while getopts ":f:o:m:t:n:c:g:e:h" flag
do
case "${flag}" in
f)
fasta=${OPTARG}
;;
o)
out_name=${OPTARG}
;;
m)
memory=${OPTARG}
;;
t)
time=${OPTARG}
;;
n)
number=${OPTARG}
;;
c)
cores=${OPTARG}
;;
g)
gpus=${OPTARG}
;;
e)
extra=${OPTARG}
;;
h)
usage
;;
:)
echo "Invalid option: $OPTARG" 1>&2
usage
exit 1
;;
\?)
echo "Invalid option"
usage
exit 1
;;
esac
done
python3 /scratch/amolinav/programs/my_script_single.py ${fasta} ${out_name} ${memory} ${time} ${number} ${cores} ${gpus} ${extra}
I would really appreciate if someone could point out where I am making the mistake.
Thank you so much in advance for your help

How to exit recent getopts options?

My script:
run() {
while getopts ":dr" option; do
case "$option" in
d) echo "__DEBUG__";;
r) echo "__RELEASE__";;
esac
done
if [ $option -eq ""]
then
echo "__DEBUG__" ;
fi
}
Hi, i'm using zsh. When i call run without any options
$ run
$ __ DEBUG __
in the first time it's ok and show DEBUG
Then i call with option (d/r) and call run with no agrument again it show this error
$ run -r
$ __ RELEASE __
$ run
$ run-9: parse error: condition expected: r
I don't know how to fix this, it seem that the while loop still has effect
You need to reset OPTIND before the getopts call at the start of your function, this will not be done automatically in this case. In bash, it is set to 1 when a shell or shell script starts, but not when a function is called.
This seems to be what POSIX getopts specifies.
Whenever the shell is invoked, OPTIND shall be initialized to 1.
zsh getopts behaves differently (thanks #PesaThe):
OPTIND has an initial value of 1, and is normally set to 1 upon entry to a shell function and restored upon exit.
Also, when getopts has finished parsing, option will be set to ?, which will not help you determine whether a (valid) option was provided.
Try something like this:
run() {
OPTIND=1
found=0
while getopts ":dr" option; do
case "$option" in
d) echo "__DEBUG__"; found=1 ;;
r) echo "__RELEASE__"; found=1 ;;
esac
done
if [ $found -eq 0 ]
then
echo "__DEBUG__" ;
fi
}
Or a bit simpler (but not identical to yours, to illustrate):
run() {
OPTIND=1
mode="__DEFAULT__"
while getopts ":dr" option; do
case "$option" in
d) mode="__DEBUG__" ;;
r) mode="__RELEASE__" ;;
esac
done
echo "$mode"
}

Bash long options/flags - how to do it?

I am trying to change my working script with getopts to getopt ( long flags ).
Below i present my code which is working.
getopts 'm:' mode
modeValue=$OPTARG
getopts 'p:' parameter
parameterValue=$OPTARG
getopts 'u:' parameter
parameterValue2=$OPTARG
getopts 'l:' parameter
parameterValue3=$OPTARG
getopts 'n:' parameter
parameterValue4=$OPTARG
getopts 'e:' parameter
parameterValue5=$OPTARG
getopts 'w:' parameter
parameterValue6=$OPTARG
getopts 'r:' parameter
parameterValue7=$OPTARG
case $modeValue in
addRepository)
doAddRepository "$parameterValue" "$parameterValue7"
exit $?
;;
addProject)
doAddProject "$parameterValue"
exit $?
;;
addUser)
doAddUser "$parameterValue2" "$parameterValue4" "$parameterValue5" "$parameterValue6"
exit $?
;;
assignProject)
doAssignProject "$parameterValue" "$parameterValue2" "$parameterValue3"
exit $?
;;
*)
#echo "$doShowUsage"
exit 1
;;
esac
Now my script is working like example below:
For add repository: ./script.sh -m addRepository -p NameOfTheProject -r NameOfTheRepository
I want to edit this for something like this:
./script.sh --mode addRepository --project NameOfTheProject --repo NameOfTheRepository
I started to modify code and added something what i present below:
TEMP=`getopt -o m:p:u:l:n:e:c:r: --long mode:,project:,username:,level:,name:,email:,pass:,repo: -n 'test.sh'
-- "$#"` eval set -- "$TEMP"
while true ; do
case "$1" in
-m|--mode)
case "$2" in
addRepository)
doAddRepository=$2 ; shift 2 ;;
addProject)
doAddProject=$2 ; shift 2 ;;
addUser)
doAddUser=$2 ; shift 2 ;;
assignProject)
doAssignProject=$2 ; shift 2 ;;
esac ;;
-h|--help)
case "$2" in
*) echo "$doShowUsage"
exit 1
esac ;;
esac done
My question is : Am I doing it in the right way ? How can I add parameters to the functions "doAddProject/Repository/User...?" Can someone give me some advices? Above functions got different amount of parameters so take a look at it.
Thank you!
Stephane Chazelas wrote a very fine getops-long shell script that I use in my bash debugger. You can copy that script and use it.
If you run that program setting variable test_getopts_long, e.g.
test_getopts_long=1 bash getopts_long.sh
you'll see extensive examples for how to use, and it tests itself.

BASH - getopts not working properly

I'm currently having problems with my script. Basically, what I want to happen is when I execute ./apache_new_vhost.sh -a -d google.com, it will create a file and directories and if I use the -r option, it should delete.
The script was able to use the functions like add_vhost. It could create a configuration and folder however the filename is empty because it could not read the value I passed to $domain.
while getopts ":a:r:d:h" opt; do
case $opt in
a) action=add_vhost
;;
r) action=remove_vhost
;;
d) domain=$OPTARG
;;
h) usage
exit 1
;;
\?) echo "Invalid option: -$OPTARG"
usage
exit 1
;;
:) echo "Error: option -$OPTARG requires an argument."
usage
exit 1
;;
esac
done
#if [ -z $domain ]; then
# usage
# exit 1
if [ $action == "add_vhost" ]; then
echo $action $domain
elif [ $action == "remove_vhost" ]; then
echo $action $domain
fi
The options are processed in the order you specify them on the command line. So in your example, case a) is processed first, and calls your add_vhost function right then.
But the d) case hasn't been processed yet, so you haven't set domain.
You need to change your logic a bit. Rather than calling your functions directly from the case statement, save what action was selected. i.e.:
a) action="add_vhost"
;;
Then after the case, check that you do have an action selected, and call that function.
As per your script you expect argument after option -a. So when you execute your script by
./apache_new_vhost.sh -a -d google.com
then -d will consider as argument given to -a option. So your second argument discarded.To solve it just give any argument after -a (ex: ./apache_new_vhost.sh -a 1 -d google.com )option or make changes in your getopt
while getopts ":ar:d:h" opt; do

Resources