I am trying to write a simple script to do something depending on the input arguments. Here is what I have written
#!/bin/bash
usage() { echo "Usage: $0 [-l <string>] [-p <string>] [-d <string> ]" 1>&2; exit 1; }
while getopts ":l:p:d" o; do
case "${o}" in
l)
l=${OPTARG}
echo "$l"
;;
p)
p=${OPTARG}
echo "$p"
;;
d)
d=${OPTARG}
echo "$d"
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ -z "${l}" ] && [ -z "${p}" ] && [ -z "${d}" ]; then
usage
fi
Its able to parse the inputs given as -l and -p properly but the third input -d is not parsed.
Output:
sagar#CPU:~/$ ./play.sh -l "l is parsed" -p "p is parsed" -d "d is parsed"
l is parsed
p is parsed
This works
sagar#CPU:~/$ ./play.sh -p "p is parsed"
p is parsed
Whereas this doesn't work
sagar#CPU:~/$ ./play.sh -d "d is parsed"
Usage: ./play.sh [-l <song name>] [-p <song name>] [-d <song name> ]
What am I doing wrong here?
Thanks for your help in advance.
You are missing : in while statement passing arguments
#!/bin/bash
usage() { echo "Usage: $0 [-l <string>] [-p <string>] [-d <string> ]" 1>&2; exit 1; }
while getopts ":l:p:d:" o; do
case "${o}" in
l)
l=${OPTARG}
echo "$l"
;;
p)
p=${OPTARG}
echo "$p"
;;
d)
d=${OPTARG}
echo "$d"
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ -z "${l}" ] && [ -z "${p}" ] && [ -z "${d}" ]; then
usage
fi
Run :
./script.sh -l "l is parsed" -p "p is parsed" -d "d is parsed"
Output :
l is parsed
p is parsed
d is parsed
Run :
./script.sh -d "d is parsed"
Output :
d is parsed
Related
I want to pass the debug facility as an user-input in a bash script. Let's take the below code as a sample script.
#!/bin/bash
usage() { echo "Usage: $0 [-d <Integer>] [-m <String>]" 1>&2; exit 1; }
while getopts "hld:p:" o; do
case "${o}" in
d)
d=${OPTARG}
[[ $d =~ ^[0-9]+$ ]] || usage
;;
p)
p=${OPTARG}
[[ $p =~ [a-zA-Z] ]] || usage
;;
l) # to enable logging/debug -- set -x
l=${OPTARG}
;;
h|*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ -z "${d}" ] || [ -z "${m}" ]; then
usage
fi
echo "d = ${d}"
echo "m = ${m}"
How can I add it in this?
getops argument, help message and case statement are not consistent:
getops argument d:h:p:, specifies options -d -h and -p (also h: means -h requires an argument)
help message, documents options -d and -m
case statement, handles options -d -p -l and -h ..
Adding l in getopts argument and removing : after using h
while getopts "d:hlp:" o; do
case "${o}" in
...
l) set -x
;;
...
esac
done
I want a script to take in two options, both are required. if I pass one in, the script doesn't print an error requesting you to pass in a second one.
-bash-4.2$ bash test.sh -b
Invalid option: b requires an argument
-bash-4.2$ bash test.sh -p
Invalid option: p requires an argument
-bash-4.2$ bash test.sh -b sdfsfd
-bash-4.2$ bash test.sh -p sdfsfd
-bash-4.2$ bash test.sh -b sdfsfd -s sfd
Invalid option: s
Code
showHelp()
{
cat << EOF
Find files in client's folder and upload to S3 bucket.
Usage: $(basename $0) [-p PATH_TO_SEARCH] [-b S3 bucket]
OPTIONS:
-h Show this help message
-p Path to search
-b S3 Bucket
EOF
exit 1
}
while getopts ":p:b:h" o; do
case "${o}" in
h)
showHelp
;;
p)
p=${OPTARG}
;;
b)
b=${OPTARG}
;;
\? )
echo "Invalid option: $OPTARG";;
: )
echo "Invalid option: ${OPTARG} requires an argument";;
esac
done
shift $((OPTIND-1))
if [ -z "${p}" ]; then
showHelp
fi
if [ -z "${b}" ]; then
showHelp
fi
If you want to ensure you get both options, you can use something like:
no_p=1
no_b=1
while getopts ":p:b:h" o; do
case "${o}" in
h)
showHelp
;;
p)
p=${OPTARG}
no_p=0
;;
b)
b=${OPTARG}
no_b=0
;;
\? )
echo "Invalid option: $OPTARG";;
: )
echo "Invalid option: ${OPTARG} requires an argument";;
esac
done
[[ $no_p -eq 1 ]] && echo "No -p provided" && exit 1
[[ $no_b -eq 1 ]] && echo "No -b provided" && exit 1
TABLE=`echo "${1}" | tr '[:upper:]' '[:lower:]'`
if [ $1 = -d ]
then TABLE=daminundation
elif [ $1 = -b ]
then TABLE=burnscararea
elif [ $1 = -r ]
then TABLE=riverpointinundation
elif [ $1 = " " ]
then echo "User must input -d (daminundation), -b (burnscararea)
or -r (riverpointinundation)."
fi
SHAPEFILEPATH=${2}
MERGEDFILENAME=${3}
if [ -z $3 ] ;
then MERGEDFILENAME=merged.shp
else
MERGEDFILENAME=${3}
fi
COLUMNNAME=${4}
if [ -n $4 ]
then COLUMNNAME=$4
fi
$3 & $4 are optional arguments. However, if I choose not to use $3 but I want to use $4, it will read the command as $3. Confused by other methods, how should I make it so that an undesired optional command can be bypassed for the next one?
You probably want this:
#!/bin/bash
while getopts ":b :d :r" opt; do
case $opt in
b)
TABLE=burnscararea
;;
d)
TABLE=daminundation
;;
r)
TABLE=riverpointinundation
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
shift $((OPTIND-1))
[ -z "$TABLE" ] && ( echo "At least one of -b/-d/-r options must be provided"; exit 1; )
[ $# -ne 3 ] && ( echo "3 params expected!"; exit 1; )
SHAPEFILEPATH="$2"
MERGEDFILENAME="$3"
COLUMNNAME="$4"
# other stuff
I am running the below script, but it looks like the $filename or $srvname did not get the input value.
say for eg: ./test.sh -n abcd.net gives the output echo 'Filename or node name must be defined.'
it means that, the $srvname did not get the value "abcd.net", please advise am i doing anything wrong. ?
set -x
usage () {
echo "usage: $0 -n <nodename>"
echo "usage: $0 -f <filename>"
echo "usage: $0 -h <help>"
}
while getopts ":nfh:" opt; do
case "$opt" in
n) srvname="$OPTARG" ;;
f) filename="$OPTARG" ;;
h) # help
usage
exit 0
;;
:) echo "Error: -$OPTARG requires an argument"
usage
exit 1
;;
?) echo "Error: unknown option -$OPTARG"
usage
exit 1
;;
esac
done
function dosomecheck {
echo "do some checks"
}
if [ "$filename" != "" ] ; then
# read file
for x in `cat $filename` ; do
dosomecheck $x
done
fi
if [ "$srvname" != "" ] ; then
# read file
for x in $srvname ; do
dosomecheck $x
done
fi
Thanks in advance
Try doing:
while getopts ":n:f:h" opt;
because -n and -f takes argument while -h doesn't.
I'm trying to put together a script to monitor files and im having a hard tiem with getopts. If I run more than once the shell values dont changes... There's a ton of clean up but I've been stuck on this one issue for a couple hours so ...
#!/bin/bash
function printUsage {
echo "Usage: $0 [-e environment] [-r region] [-l logtype]"
echo "Requirements:"
echo " -e environment to look in; prod or dev"
echo " -r 3 digit region designation"
echo " -l log type to find; soap, message, main, service, or detail"
echo " example: $0 -e dev -r 111 -f soap"
exit 0
}
if [ $# -lt 1 ]; then
printUsage
fi
while getopts "e:r:l:" opt; do
case $opt in
e)
environment="$OPTARG"
;;
r)
region="$OPTARG"
;;
l)
logtype="$OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG"
printUsage;;
:)
echo "-$OPTARG requires an argument"
printUsage;;
esac
done
#build array of directories to search based on argument
function buildProductionArray {
# assume these are here
logpaths=( )
}
#build array of directories to search based on argument
function buildDevArray {
# assume these are here
logpaths=( )
}
function validateArguments {
#validate the environment
if [ "$(echo "$environment" | tr "[:lower:]" "[:upper:]")" == "PROD" ]; then
buildProductionArray
elif [ "$(echo "$environment" | tr "[:lower:]" "[:upper:]")" == "DEV" ]; then
buildDevArray
else
echo "Usage: findlog [-e environment] [-r region] [-l logtype]"
echo "Invalid environment" >&2; exit 1
fi
#validate the region
if ! [ "$region" -eq "$region" ] 2>/dev/null; then
echo "Usage: findlog [-e environment] [-r region] [-l logtype]"
echo "Invalid region" >&2; exit 1
fi
#validate the logtype
function in_array() {
elements=${1}
element=${2}
for i in "${elements[#]}" ; do
if [ "$i" == "$element" ] ; then
return 1
fi
done
return 0
}
logvalues=(soap message service main detail)
log="$(echo "$logtype" | tr '[:upper:]' '[:lower:]')"
echo "$log"
if in_array logvalues "${log}"; then
if [[ "$log" == "service" || "$log" == "detail" ]]; then
log="-$log-time-"
else
log="-$log-"
fi
else
echo "Usage: findlog [-e environment] [-r region] [-l logtype]"
echo "Invalid environment" >&2; exit 1
fi
}
validateArguments
for i in "${logpaths[#]}"
do
#assume this is here
done