I'm trying to make script for multiple input data files. What is the best way, how to handle that arguments? Usage of script should be:
./script.sh -a sth -b sth - c sth -d sth input1 input2 input3
I can handle parameters and arguments using getopts, but I have no idea, how to handle these input files, because there is no flag for them.
Thanks
while getopts ":a:b:c:d:" opt; do
case "$opt" in
a) i=$OPTARG ;;
b) j=$OPTARG ;;
c) k=$OPTARG ;;
d) l=$OPTARG ;;
esac
done
shift $(( OPTIND - 1 ))
for file in "$#"; do
# your stuff here
done
Please try this, this may solve the purpose for you
My own comment has prompted me to extend the answer:
In case you want to do it only from getopts:
You will have to call the script as
./script -a hj -b op -c zx -d some -f "File in list seperated with spaces"
while getopts ":a:b:c:d:f:" opt; do
case "$opt" in
a) i=$OPTARG ;;
b) j=$OPTARG ;;
c) k=$OPTARG ;;
d) l=$OPTARG ;;
f) files=$OPTARG ;;
esac
done
#no shift is required now, since we have file list in $files
for file in $files; do
# your stuff here
done
Related
I am trying to extend the getopts from the sourced script as below.
if an option other than a,b,c,d is passed in, it needs to print "invalid option" and exit.
script_a.sh:
#!/bin/bash
script_a_getopts() {
while getopts 'a:b:' OPT; do
case "$OPT" in
a)
a=$OPTARG
;;
b)
b=$OPTARG
;;
*)
echo "invalid option"
exit 1
;;
esac
done
}
script_b.sh
#!/bin/bash
source script_a.sh
while getopts ':c:d:' OPT; do
case "$OPT" in
c)
c=$OPTARG
;;
d)
d=$OPTARG
;;
[?])
script_a_getopts $#
esac
done
echo "a=$a"
echo "b=$b"
echo "c=$c"
echo "d=$d"
When I run the script, it don't work as expected, obviously I am making a mistake.
$ ./script_b.sh -c cat -d dog -a apple -b boy
a=
b=
c=cat
d=dog
Didn't throw error when -x is passed.
$ ./script_b.sh -x
a=
b=
c=
d=
Short Answer: You have to rollback the OPTIND before calling script_a_getopts.
case "$OPT" in
c)
c=$OPTARG
;;
...
[?])
let OPTIND--
script_a_getopts $#
esac
done
Long Answer:
The getopts track which arguments have been processed using the OPTIND variable. When the top getopts recognized unknown item, it has already 'consumed' it by moving OPTIND to the next argument. To get script_a_getopts to process that argument, the OPTIND need to be rolled back to point to the unprocessed argument.
The let OPTIND-- will allow the unrecognized argument to be re-processed.
Side note, if you want to allow options to be placed in arbitrary order (-c cat -a apple -d dog -b boy) you will have to repeat the same in the script_a_getopts. This will require improved error processing in script_a_getopts function.
Background
In bash I have a working getopts interface as depicted below:
while getopts "a:b:c:d:" OPTION ; do
case "$OPTION" in
a) JET="$OPTARG" ;;
b) FUEL="$OPTARG" ;;
c) CAN="$OPTARG" ;;
d) MELT="$OPTARG" ;;
*) echo "Usage $0 -a A -b B -c C -d D"; exit 1 ;;
esac
done
shift $((OPTIND-1))
#Check out input parameters
for PARAM in JET FUEL CAN MELT; do
echo "$PARAM in [${!PARAM}]"
done
Question
What is the cshell translation for this? I cannot find a clear example of getopts (with an s) in cshell, yet there is an easily findable one for bash. This is distinct from attempting to use getopt, since getopts is an entirely different function from getopt.
I want to do two things in this script:
1) pass a file name to the script
2) pass options to the script
example 1:
$./test_script.sh file_name_to_be_read
pass only file names to script
example 2:
$./test_script.sh -a -b file_name_to_be_read
pass file name and options to script
I am able to get example 1 to work using the following codes:
while read -r line ; do
echo $line
done
In example 2, I want to add additional flags like these:
while getopts "abc opt; do
case "$opt" in
a) a=1
echo "a is enabled"
;;
b) b=1
echo "b is enabled"
;;
esac
done
but how do I make it so that the file_name to be mandatory and be used with or without options?
getopts only parses options (arguments starting with -); the other arguments are left alone. The parameter OPTIND tells you the index of the first argument not yet looked at; typically you discard the options before this.
while getopts "ab" opt; do
case "$opt" in
a) a=1
echo "a is enabled"
;;
b) b=1
echo "b is enabled"
;;
esac
done
shift $((OPTIND - 1))
echo "$# arguments remaining"
for arg in "$#"; do
echo "$arg"
done
The preceding, if called as bash tmp.bash -a -b c d e, produces
$ bash tmp.bash -a -b c d e
a is enabled
b is enabled
3 arguments remaining:
c
d
e
I am working on a shell script that allows users to set options.
The script is working fine if the user specifies options seperately. For instance:
./my_file.sh -r -l directory1 directory2
The command above is working perfectly, however my script doesn't work if the user specifies the following command:
EDIT: What I mean is that the -l option is not recognized if the user enters the command below
./my_file.sh -rl directory1 directory2
This is the code I am using to read the options
while getopts 'lvibrd:v' flag; do
case "${flag}" in
l) option_l=true
shift ;;
v) option_v=true
shift ;;
i) option_i=true
shift ;;
b) option_b=true
shift ;;
r) option_r=true
shift ;;
d) option_d=true
shift ;;
*) echo "Invalid options ${flag}"
exit 1 ;;
esac
done
Is there a way to read options with multiple letters, such as -rl, using similar code?
Thank you in advance.
Try the following (simplified):
while getopts 'lr' flag; do
case "$flag" in
l) echo "option -l was set";;
r) echo "option -r was set";;
*) echo "Invalid options ${flag}"
exit 1 ;;
esac
done
shift $(($OPTIND - 1))
echo "$#"
Omitted shift makes the difference. The shifting confuses getopts builtin.
This works correctly for both single and combined options:
$ ./nic.sh -rl hello world
option -r was set
option -l was set
hello world
EDIT: I've added code to print the rest of arguments (after those processed by getopts).
I'd like to pass options as a parameter. E.g.:
mycommand -a 1 -t '-q -w 111'
The script cannot recognize a string in quotes. I.e it gets only part of the string.
getopts works the same - it see only -q.
For custom getopts I use similar script (example):
while :
do
case $1 in
-h | --help | -\?)
# Show some help
;;
-p | --project)
PROJECT="$2"
shift 2
;;
-*)
printf >&2 'WARN: Unknown option (ignored): %s\n' "$1"
shift
;;
*) # no more options. Stop while loop
break
;;
--) # End of all options
echo "End of all options"
shift
break
;;
esac
done
Maybe I misunderstand the question, but getopts seems to work for me:
while getopts a:t: arg
do
case $arg in
a) echo "option a, argument <$OPTARG>"
;;
t) echo "option t, argument <$OPTARG>"
;;
esac
done
Run:
bash gash.sh -a 1 -t '-q -w 111'
option a, argument <1>
option t, argument <-q -w 111>
Isn't that what you want? Maybe you missed the : after the options with arguments?