How to get the agrument after the command using GETOPTS in BASH - bash

Example of script usage
./myscript --p 1984 --n someName
#!/bin/bash
while getopts :npr opt
do
case $opt in
n ) echo name= ??? ;;
p ) echo port= ??? ;;
r ) echo robot= "Something" ;;
? ) echo "Useage: -p [#]" ;;
esac
done
How to I access the argument following the command option?
Moreover, if i type: ./myscript --p 1985 I would like to know how ot echo 1985 back and work with that argument.

In bash, see help getopts: "When an option requires an argument, getopts places that argument into the shell variable OPTARG."
usage() { echo "Usage: $(basename $0) -n name -p port -r"; exit; }
while getopts :n:p:r opt # don't forget the colons for opts that take an arg
do
case $opt in
n ) name="$OPTARG" ;;
p ) port="$OPTARG" ;;
r ) robot=chicken ;;
? ) usage ;;
esac
done
shift $(( OPTIND - 1 ))
echo "the name is $name"
echo "the port is $port"
I'm sure you could google around for a solution to parse options in bash. Here's a couple minutes' effort:
#!/bin/bash
usage() { echo foo; exit; }
while [[ $1 == -* ]]; do
case "$1" in
--) shift 1; break ;;
-p|--p|--port) port="$2"; shift 2;;
-n|--n|--name) name="$2"; shift 2;;
*) echo "unknown option: $1"; usage;;
esac
done
echo "the name is $name"
echo "the port is $port"
echo "the rest of the args are:"; ( IFS=,; echo "$*" )
And a test,
$ bash longopts.sh --port 1234 --bar a b c
unknown option: --bar
foo
$ bash longopts.sh --port 1234 a b c
the name is
the port is 1234
the rest of the args are:
a,b,c

Related

Shell script with parameters?

I have a shell script that takes parameters, below is the code..
Right now it will only accept parameters if passed if called like this: script.sh --mode=load (or -m=load)
Is there a way to modify this so that it can be called with or without the "=" sign, so that I can call: script.sh --mode load (or -m load)
Ideally needs to work in pure bash as I don't have access to install additional tools, etc.
for i in "$#"
do
case $i in
-m=*|--mode=*)
MODE="${i#*=}"
if [[ $MODE =~ ^(dump|load)$ ]]; then
echo "" > /dev/null
else
bark "Invalid --mode set, set this to dump or load.";
exit 1
fi
;;
-p=*|--db-path=*)
DBPATH="${i#*=}"
;;
-d=*|--dump-dir=*)
DUMPDIR="${i#*=}"
;;
-l=*|--list-file=*)
TABLES="${i#*=}"
# check if file exists on disk
if [ -e $TABLES ]
then
echo "" >> /dev/null
else
bark "Table file not found!";
exit 1
fi
;;
-t=*|--tenant-name=*)
TENANT="${i#*=}"
# check if tenant is correct
if [[ $TENANT =~ ^($TENANT_LIST)$ ]]; then
echo "" >> /dev/null
else
bark "Tenant name does not match, aborting.";
exit 1
fi
;;
-s|--shared)
SHARED=YES
;;
*) usage # unknown option
;;
esac
done
My bash version:
bash --version
GNU bash, version 4.3.22(1)-release (powerpc-ibm-aix5.1.0.0)
Loop on $#. When $1 is "-m", do a shift. So in the next loop $1 will now be the argument to the -m option.
script.sh --mode load
# FIRST LOOP
$# is "--mode load"
$1 is "--mode"
shift
# SECOND LOOP
$# is "load"
$1 is "load"
This is also useful if you can specify many arguments instead of just one like you have right now. Error checking should be done to validate your argument values, and if a user did script.sh --mode with no other argument.
Don't reinvent the wheel.
If you're OK with just 1 character options, use the bash builtin getopts
#!/bin/bash
while getopts :m:p:d:l:t:s opt; do
case $opt in
m) mode=$OPTARG ;;
p) dbpath=$OPTARG ;;
d) dumpdir=$OPTARG ;;
l) tables=$OPTARG
# test file existence
;;
t) tenant=$OPTARG
# test tenant
;;
s) shared=YES ;;
:) echo "Missing argument for option -$OPTARG" >&2
exit 2
;;
*) echo "Invalid option -$OPTARG" >&2
exit 2
;;
esac
done
shift $((OPTIND - 1))
cat << SHOW_VARS
I have:
mode=$mode
dbpath=$dbpath
dumpdir=$dumpdir
tables=$tables
tenant=$tenant
shared=$shared
rest of args=$*
SHOW_VARS
Otherwise, you may be able to use the external getopt program to help parse your args. I don't have an AIX box to test on, so YMMV
tempargs=$(
getopt \
-o m:d:l:t:s \
--long mode:,db-path:,dump-dir:,list-file:,tenant-name:,shared \
-- "$#"
)
if [[ $? -ne 0 ]]; then echo "Error..." >&2; exit 2; fi
eval set -- "$tempargs"
while true; do
case $1 in
-m|--mode) mode=$2; shift 2;;
-p|--db-path) dbpath=$2; shift 2;;
-d|--dump-dir) dumpdir=$2; shift 2;;
-l|--list-file) tables=$2
# test file existence
shift 2
;;
-t|--tenant-name) tenant=$2
# test tenant
shift 2
;;
-s|--shared) shared=YES; shift;;
--) shift; break ;;
*) echo "Error..." >&2; exit 2 ;;
esac
done

How to read inline parameters using command line args in bash script?

I have a bash script which takes few command line args and a filename as inline parameter. I am not able to read the inline parameter.
sh test.sh -a a -b b -c c < pwd.txt
test.sh has
if [ $# = 0 ]
then
echo $USAGE >&2
exit $STATUS_ERROR_FAIL
fi
# Parse command line options.
while getopts a:b:c: OPT;
do
case "$OPT" in
a)
a="$OPTARG"
;;
b)
b="$OPTARG"
;;
c)
c="$OPTARG"
;;
\?)
# getopts issues an error message
echo $USAGE
exit $STATUS_ERROR_FAIL
;;
esac
done
shift $((OPTIND-1))
echo "1=$1"
your script is working fine, your error is
echo "1=$1"
if you want to see your parameter you should add an echo/print in your case
#!/bin/bash
if [ $# = 0 ]
then
echo $USAGE >&2
exit $STATUS_ERROR_FAIL
fi
# Parse command line options.
while getopts a:b:c: OPT;
do
case "$OPT" in
a)
a="${OPTARG}"
echo "a[$a]"
;;
b)
b="${OPTARG}"
echo "b[$b]"
;;
c)
c="${OPTARG}"
echo "c[$c]"
;;
\?)
# getopts issues an error message
echo $USAGE
exit $STATUS_ERROR_FAIL
;;
esac
done
shift $((OPTIND-1))
or
you can add the echo/print at the end of the script.. it's depend by your needs
output
[shell] ➤ ./t -a 1 -b 2 -c 3
a[1]
b[2]
c[3]
Regards
Claudio

parse arguments after getopts

I want to call a bash script like this
$ ./scriptName -o -p -t something path/to/file
This is as far as I get
#!/bin/bash
o=false
p=false
while getopts ":opt:" options
do
case $options in
o ) opt1=true
;;
p ) opt2=true
;;
t ) opt3=$OPTARG
;;
esac
done
but how do I get the path/to/file?
You can do something like:
shift $(($OPTIND - 1))
first_arg=$1
second_arg=$2
after the loop has run.
To capture all the remaining parameters after the getopts processing, a good solution is to shift (remove) all the processed parameters (variable $OPTIND) and assign the remaining parameters ($#) to a specific variable.
Short answer:
shift $(($OPTIND - 1))
remaining_args="$#"
Long example:
#!/bin/bash
verbose=false
function usage () {
cat <<EOUSAGE
$(basename $0) hvr:e:
show usage
EOUSAGE
}
while getopts :hvr:e: opt
do
case $opt in
v)
verbose=true
;;
e)
option_e="$OPTARG"
;;
r)
option_r="$option_r $OPTARG"
;;
h)
usage
exit 1
;;
*)
echo "Invalid option: -$OPTARG" >&2
usage
exit 2
;;
esac
done
echo "Verbose is $verbose"
echo "option_e is \"$option_e\""
echo "option_r is \"$option_r\""
echo "\$# pre shift is \"$#\""
shift $((OPTIND - 1))
echo "\$# post shift is \"$#\""
This will output
$ ./test-getopts.sh -r foo1 -v -e bla -r foo2 remain1 remain2
Verbose is true
option_e is "bla"
option_r is " foo1 foo2"
$# pre shift is "-r foo1 -v -e bla -r foo2 remain1 remain2"
$# post shift is "remain1 remain2"

How do you use getopts?

what is the easiest, most straight forward, way to use getopts in bash script.
if i have a script called: myscript and it CAN take the the arguments: -p -r -s -x
if argument x then exit
if argument p then echo "port 10"
if argument s then add 2+2
if argument r then echo env
This is a hypothetical script but I would just like to see an example of how this would be done.
while getopts :xpsr opt; do
case $opt in
x ) exit ;;
p ) echo port 10 ;;
s ) (( 2 + 2 )) ;;
r ) echo env ;;
\? ) echo "${0##*/}" [ -xpsr ]; exit 1 ;;
esac
done
usage()
{
echo "Usage: $0 [-o <offset>] [-h];"
exit 0;
}
# -o (offset) need a value
# -h prints help
offset=0 # 0 is default offset
while getopts o:s opt
do
case "$opt" in
d) offset="$OPTARG";; # changing offset
s) usage # calls function "usage"
\?) echo "$OPTARG is an unknown option"
exit 1;; # all other options
esac
done
shift $((OPTIND-1))

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