Bash getopt to accept multiple parameters [duplicate] - bash

This question already has answers here:
Multiple option arguments using getopts (bash)
(4 answers)
Closed 1 year ago.
I am writing a script using getopt to parse parameters. The solution I have so far only accepts one parameter. Is there a way to make this solution accept multiple parameters (eg. both '-f and -l)?
solution in link does not work for me.
Bash getopt accepting multiple parameters
code:
'''
while getopts "f:l:" option; do
case "${option}" in
f) firstdate=${OPTARG}
shift
;;
l) lastdate=${OPTORG}
;;
*)
echo "UsageInfo"
exit 1
;;
esac
shift
done
'''

First, you have a typo: OPTORG should be OPTARG.
More importantly, you don't need the calls to shift. getopts takes care of consuming and skipping over each option and argument.
while getopts "f:l:" option; do
case "${option}" in
f) firstdate=${OPTARG} ;;
l) lastdate=${OPTARG} ;;
*)
echo "UsageInfo"
exit 1
;;
esac
done

Related

How does a Bash for loop read script parameters? [duplicate]

This question already has answers here:
What is $opt variable for command line parameter in bash
(3 answers)
Closed 4 years ago.
Normally, script parameters are read from $1, $2, ...
Sometimes this is combined with shift and a while-loop and case-statement to process multiple parameters.
while [[ $# > 0 ]]; do
case "$1" in
-v|--verbose)
VERBOSE=1
;;
-d|--debug)
VERBOSE=1
DEBUG=1
;;
*) # unknown option
echo 1>&2 -e "${COLORED_ERROR} Unknown command line option '$key'.${ANSI_NOCOLOR}"
exit 1
;;
esac
shift # parsed argument or value
done
Today, I found a code snippet based on a simple for-loop:
#! /bin/bash
for opt; do
echo $opt
done
Execution:
$ ./test.sh foo bar spam
foo
bar
spam
Normally, one would see for i in ...; do.
Why/how can a simplified for-loop access script parameters?
Does it also work with parameters in functions?
From help for:
If in WORDS ...; is not present, then in "$#" is assumed.

How do I make an option accept an arbitrary number of arguments

I am trying to write a shell script with options that take different numbers of values in each run, e.g.
Run 1:
./myscript --input <file1> <file2> --output <folder1>
Run 2:
./myscript --input <file1> <file2> <file3> --output <folder1> <folder2>
I tried using getopts as follows:
while getopts ":i:o:" opt; do
case $opt in
i)
echo "treatment files are: $OPTARG" >&2
infiles="${OPTARG}"
;;
o)
echo "control files are: $OPTARG" >&2
outdir="${OPTARG}"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
However, the only way I found to input variable amounts of values for the "-i" option is by quotation ("file1 file2"), which prevents me/the user to use the autocomplete function of the command line to help generating the file path. Also this option does not seem allow me to use "--input" syntax to pass the options.
Anybody can help?
Thanks a lot.
You have two questions here. One of them is "how do I implement long options in my shell script?", for which there is good reading here.
The other question is, "how do I make an option accept an arbitrary number of arguments?" The answer there is, mostly, "you don't". Often the cleanest solution is to have your script accept the option multiple times, as in:
./myscript -i <file1> -i <file2> -i <file3>
This is relatively easy to handle by appending to a Bash array, as in:
infiles=()
while getopts ":i:o:" opt; do
case $opt in
i)
infiles+=("${OPTARG}")
;;
esac
done
And later on you can iterate over those values:
for inputfile in "${infiles[#]}"; do
...
done
Read about bash arrays for more information.
If you don't like that solution, you could implement your own option parsing in a manner similar to some of the answers to the question to which I linked in the first paragraph. That would allow you to get the command line semantics you want, although I would argue that behavior is at odds with the way a typical program behaves.

How to use getopts in bash script? [duplicate]

This question already has answers here:
Optional option argument with getopts
(15 answers)
Closed 5 years ago.
I'm trying to use getopts like this:
#!/bin/bash
while getopts "i" option
do
case "${option}"
in
i) INT=${OPTARG};;
esac
done
echo "$INT"
But it prints $INT only if i use getopts "i:". If I understand correctly, the colons in the optstring mean that values are required for the corresponding flags. But I want to make this flag optional.
Can anyone explain why the script acts like this and how can I fix it?
You cannot make it (bash getopts) optional like that. The "getopts" does not support mandatory or optional options.
You would need to code for that.
And if a ":" is specified then there needs to be an argument to that option. There is no way to around it.
The following code snippets shows how to check for mandatory arguments.
# Mandatory options
arg1=false;
..
...
case "${option}"
in
i) INT=${OPTARG}; arg1=true;
;;
esac
if ! $arg1;
then
echo -e "Mandatory arguments missing";
# assuming usage is defined
echo -e ${usage};
exit 1;
fi

bash - getopts in switch case

I'm trying to use getopts inside a switch case loop.
if i use only getopts or only the switch case it's work, however when i combine those two the getopts dos not trigger.
i have search a lot but i cat fins any mention for how to combine them, and problem i missing something stupid so for give me ...
here is the code essence.
#!/bin/bash
case $1 in
ver)
echo "vesion"
exit 0
;;
op)
while getopts ":a" opt; do
case $opt in
a)
echo "-a was triggered!" >&2
;;
\?)
echo "Invalid option: -$OPTARG" >&2
;;
esac
done
;;
esac
when i do that
# bash -x test.sh op -a
i get
+ case $1 in
+ getopts :a opt
(and without debug i get nothing)
what is that that i missing to combine these two
Thanks :)
You should add a shift instruction at the beginning of your op) choice, before the call to getopts, to eat the op argument itself. Else, the first argument that getopts will analyze is op and it will silently stop (end of options).

Using getopts with a switchless path

I am trying to write a short script, utilizing getopts. I want it to take optional switches, or just run as the default. I have a -d switch to enable debugging, and I'd like every other argument to be a path. The ideal command line looks as such, with paths being optional, and theoretically limitless:
$0 [-d] [/path1[ /path2[ ...]]]
I am currently using getopts as such below:
while getopts ":d" opt; do
case $opt in
d)
DEBUG=true
;;
h)
echo USAGE: $0 \[-d\] \[\/mount\/point\/1 ...\]
exit 0
;;
\?)
echo Incorrect syntax
;;
esac
done
What can I put in the while getopts section, and in the case set, to allow paths to be entered, as many as needed?
You don't need anything in the loop or getopts call for that. getopts stops at the first non-option.
After your loop all your paths will still be in positional arguments available for use.
Also you don't have h in your getopts string so it isn't valid.

Resources