Getting bash getopts to do something - bash

I am attempting to figure out how to use bash getopts to process command lines. I have the following code:
while getopts "e:n:t:s:h" opt
do
echo $opt
done
I invoke it with a bash command line like this:
. ./testopts.sh -e MyE -s sanctity
and nothing gets printed.
Please help

$opt will only print switches e or s for you but to print passed argument you need to echo $OPTARG as well.
Like this script:
while getopts "e:n:t:s:h" opt
do
echo $opt $OPTARG
done

Here is an template what i'm using for argument processing.
It is far from optimal (for example uses too much sed, instead of builtin bash regexes and so on) but you can use it for the start:
#!/bin/bash
#define your options here
OPT_STR=":hi:o:c"
#common functions
err() { 1>&2 echo "$0: Error: $#"; return 1; }
required_arg() { err "Option -$1 need argument"; }
checkarg() { [[ "$1" =~ ${optre:--} ]] && { required_arg "$2"; return 1; } || { echo "$1" ; return 0; } }
phelp() { err "Usage: $0" "$(sed 's/^://;s/\([a-zA-Z0-9]\)/ -&/g;s/:/ [arg] /g;s/ */ /g' <<< "$OPT_STR")"; return 1; }
do_work() {
echo "Here should go your script for processing $1"
}
## MAIN
declare -A OPTION
optre=$(sed 's/://g;s/.*/-[&]/' <<<"$OPT_STR")
while getopts "$OPT_STR" opt;
do
#change here i,o,c to your options
case $opt in
i) OPTION[$opt]=$(checkarg "$OPTARG" $opt) || exit 1;;
o) OPTION[$opt]=$(checkarg "$OPTARG" $opt) || exit 1;;
c) OPTION[$opt]=1;;
h) phelp || exit 1;;
:) required_arg "$OPTARG" || exit 1 ;;
\?) err "Invalid option: -$OPTARG" || exit 1;;
esac
done
shift $((OPTIND-1))
#change here your options...
echo "iarg: ${OPTION[i]:-undefined}"
echo "oarg: ${OPTION[o]:-undefined}"
echo "carg: ${OPTION[c]:-0}"
echo "remainder args: =$#="
for arg in "$#"
do
do_work "$arg"
done

OPTIND=1
while getopts "e:n:t:s:h" opt
do
case $opt in
e) echo "e OPTARG=${OPTARG} ";;
n) echo "n OPTARG=${OPTARG} ";;
t) echo "t OPTARG=${OPTARG} ";;
s) echo "s OPTARG=${OPTARG} ";;
h) echo "h OPTARG=${OPTARG} ";;
esac
done

Related

How to write if command with arguments

I've an question, how to use *if *or *case * statements to do below command :
command.sh --value string ?
I tried :
case "$1" in
[--value ])
echo "You choose value"
;;
*)
echo "plz chs diff one"
;;
esac
But it is not what I want to achieve.
I want to run command.sh --value string , where string is the first argument.
getopts is a tool that can be used to parse arguments
usage() {
echo "Usage: $0 [-v]" 1>&2
}
exit_abnormal() {
usage
exit 1
}
while getopts "v" arg; do
case $arg in
v) USE_VALUE='true' ;;
?)
echo "Invalid option: -${OPTARG}."
echo
usage
;;
esac
done
shift
if [[ $USE_VALUE == "true" ]]; then
...
fi
You can try this:
if [ "$1" = "--value" ]; then
echo "You choose value $2"
else
echo "plz chs diff one"
fi

Bash script command handler to replace long if chain

Let's say I have a bunch of if statements with the form:
if (some flag variable/argument is set) then
execute another command or bash script
This is a bit troublesome to maintain, so I was wondering if there was some other way of doing this. While this guide is for node.js, I was wondering if it is possible to achieve something similar in bash
I wonder if you're looking for something like this:
#!/bin/bash
# initialize global options
debug=false
verbose=0
main() {
local OPTIND
while getopts :hdv: opt; do
case $opt in
h) show_help; exit ;;
d) debug=true ;;
v) verbose=$OPTARG;;
:) echo "error: missing argument for -$OPTARG"; exit 1;;
?) echo "error: unknown option -$OPTARG"; exit 1 ;;
esac
done
shift $((OPTIND-1))
if [[ -z $1 ]]; then
echo "error: missing subcommand"
show_help
exit 1
fi
case $1 in
bar|baz)
# invoke the command with the arguments
"$#" ;;
*) echo "error: unknown subcommand $1"; exit 1;;
esac
}
show_help() {
echo "usage: $(basename "$0") [global opts] subcommand [local opts and args]"
echo "... more details..."
}
bar() {
echo "you called $FUNCNAME with args $*"
}
baz() {
echo "this is baz"
local OPTIND
while getopts :ab opt; do
case $opt in
a|b) echo "you selected option $opt";;
?) echo "unknown option -$OPTARG";;
esac
done
if $debug; then echo "some debug message"; fi
(( verbose > 0 )) && echo "some verbose message"
}
main "$#"
You could write a wrapper function that checks the variable and then executes the command passed in:
#!/bin/bash
run_if_set() {
local var=$1
shift
(($# == 0)) && return # nothing to run
[[ $var ]] && "$#" # execute only if var is set to a non-empty string
}
Then replace your if statements with:
run_if_set "$var" command ...
which is slightly more readable than
if [[ $var ]]; then
command ...
fi
or
[[ $var ]] && command ...

How to extract a particular pattern passed in command line argument in shell script

Like i am passing this argument to command line
trace.sh -f abc -t 20
i want to extrace (-t 20) in a variable. how to do that?
Thanks
Very basic example (not fully error prone)
err() { echo "$#" >&2; return 1; }
declare -A options
options=([f]="abc" [t]="20") #the defaults
while getopts ":f:t:" opt
do
case "$opt" in
f) options[$opt]="$OPTARG" ;;
t) options[$opt]="$OPTARG" ;;
\?) err "Invalid option -$OPTARG" || exit 1 ;;
esac
done
echo "t: ${options[t]}"
echo "f: ${options[f]}"

using getopts did not get the input value

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.

shell get opt is catputre $1 as argument

FILE_LIST=$1
MOVE=0
while getopts "m" OPT; do
case $OPT in
m) MOVE=1 ;;
M) MOVE=1 ;;
*) echo "Invalid parameter." >&2; exit 1 ;;
esac
done
echo $MOVE
echo $FILE_LIST
I will pass optional argument ( -m/-M) and file list .
test.sh -m a.txt
its display 1 -m , but i am looking for 1 a.txt
Supost if test.sh a.xt
it should be diplsay 0 and a.txt
You need to shift the arguments.
MOVE=0
while getopts "mM" OPT; do
case $OPT in
M|m) MOVE=1
shift;;
*) echo "Invalid parameter." >&2; exit 1 ;;
esac
done
echo $MOVE
FILE_LIST=$1
echo $FILE_LIST
You can also combine m and M into one case.
If I understand right, you want the syntax for running the script to be something like:
./scriptname [-mM] firstfile [secondfile ...]
If this is correct, none of the other answers quite work; here's how I'd do it:
#!/bin/bash
# Parse command options
MOVE=0
while getopts "mM" OPT; do
case "$OPT" in
m|M) MOVE=1 ;;
*) echo "Invalid option." >&2; exit 1 ;;
esac
done
shift $(( OPTIND-1 )) # Remove options from the argument list
# Parse command arguments
if [[ $# -eq 0 ]]; then
echo "No files specified." >&2
exit 1
fi
FILE_LIST=( "$#" ) # Use an array in case of spaces in filenames
# Some examples of things to do with the results:
# Work with the specified files individually:
for FILE in "${FILE_LIST[#]}"; do
chmod g+w "$FILE"
done
# Work with the specified files as a group:
if (( MOVE == 1 )); then
mv "${FILE_LIST[#]}" "$DEST_DIR"
else
cp "${FILE_LIST[#]}" "$DEST_DIR"
fi
I do not exactly know what you want but Here are some code examples:
First example assumes that the filelist is given always after the -m option
while getopts "m:" OPT
do
case $OPT in
m)
echo "option m"
FILE_LIST = $OPTARG
;;
*)
echo "error"
;;
esac
done
echo $FILE_LIST
Or a different approach with a filelist not related to the -m option
while getopts "m:" OPT
do
case $OPT in
m)
echo "option m"
MOVE = 1
;;
*)
echo "error"
;;
esac
done
shift $(($OPTIND - 1))
FILE_LIST = $1
echo $FILE_LIST
Hope this suits your needs
You have to use $OPTARG value for this. Notice m:. The colon specifies that there are arguments passed to -m
#!/bin/bash
MOVE=0
while getopts "m:M:" OPT; do
case $OPT in
m|M) MOVE=1
FILE_LIST="$FILE_LIST $OPTARG"
;;
*) echo "Invalid parameter." >&2; exit 1 ;;
esac
done
shift $(( OPTIND-1 ))
[[ $MOVE != 1 ]] && FILE_LIST=$1
echo $MOVE
echo $FILE_LIST

Resources