I need to call another shell script testarg.sh within my main script. This script testarg.sh has arguments ARG1 ,ARG2, ARG3. I need to call up the below way:
./testarg.sh -ARG1 <value> -ARG2 <value> -ARG3
ARG1 and ARG3 arguments are mandatory ones. If it's not passed to the main script then I quit. ARG2 is an optional one. If the ARG2 variable is not set with value or it's not defined then I need not pass it from main script. So I need to call up the below way
./testarg.sh -ARG1 <VALUE1> -ARG3
If the value exist for the ARG2 Variable then I need to call the below way:
./testarg.sh -ARG1 <VALUE1> -ARG2 <VALUE2> -ARG3
Do I need to have a if else statement for checking the ARG2 variable is empty or null? Is there any other way to do it?
Amendment
If ARG2 is set, then the call should be:
./testarg.sh -ARG1 -OPT2 $ARG2 -ARG3
If this is in bash, you can write
./testarg.sh -ARG1 $ARG1 ${ARG2:+-ARG2 $ARG2} -$ARG3
The construct ${param:+word} evaluates to word if param is set, or nothing otherwise. So if $ARG2 has a value, you get -ARG2 $ARG2, otherwise nothing.
#!/bin/sh
if [ "$1" = "" ]; then
echo ARG1 is null
else
echo ARG1 = $1
fi
if [ "$2" = "" ]; then
echo ARG2 is null
else
echo ARG2 = $2
fi
Related
I am not sure if switch is the proper terminology as I am new to Unix.
I have a shell script that requires what I call a switch to function properly but I also want to pass arguments:
./scriptname -cm
where if I run just ./scriptname it would fail. But I also want to pass various arguments:
./scriptname -cm arg1 arg2 arg3 arg4
This appears to fail due to the -cm. Normally when I do ./scriptname arg1 arg2 arg3 it will work properly but once I add the switch it fails. Suggestions?
Edit1:
Adding some more relevant code:
./scriptname -cm
will call
scriptname
gencmlicense()
{
echo $2
do stuff
}
gentermlicense()
{
do stuff
}
if [ "$1" = "-cm" ] ; then
gencmlicense
elif [ "$1" = "-term" ] ; then
gentermlicense
fi
If I added an argument the echo $2 would not print out the second argument passed.
If you want to pass arguments from the main script to a function unmodified, use
...
if [ "$1" = "-cm" ] ; then
gencmlicense "$#"
elif [ "$1" = "-term" ] ; then
gentermlicense "$#"
fi
The "$#" (with double quotes!) expands to all positional parameters. For more on this, see your shell manual, likely under "Parameter Expansion".
If your functions don't need the first positional parameter, you can shift it away:
if [ "$1" = "-cm" ]; then
shift
gencmlicense "$#"
elif [ "$1" = "-term" ]; then
shift
gentermlicense "$#"
fi
The professional way of handling options, though, is with the getopts builtin, because it is flexible and extensible, yet compact. This is what I use:
#!/bin/sh
MYNAME=${0##*/} # Short program name for diagnostic messages.
VERSION='1.0'
PATH="$(/usr/bin/getconf PATH):/usr/local/bin"
usage () {
cat << EOF
usage: $MYNAME [-hvVx] [-a arg] ...
Perform nifty operations on objects specified by arguments.
Options:
-a arg do something with arg
-h display this help text and exit
-v verbose mode
-V display version and exit
-x debug mode with set -x
EOF
exit $1
}
parse_options () {
opt_verbose=false
while getopts :a:hvVx option; do
case $option in
(a) opt_a=$OPTARG;;
(h) usage 0;;
(v) opt_verbose=true;;
(V) echo "version $VERSION"; exit 0;;
(x) set -x;;
(?) usage 1;;
esac
done
}
#-------------------------------------------------------------#
# Main script #
#-------------------------------------------------------------#
parse_options "$#"
shift $((OPTIND - 1)) # Shift away options and option args.
...rest of script here...
Script should pass list of values to the argument and should validate if there is one argument is passed and no list.
for example
./script --arg hi
script should do the --arg command and add/delete hi
./script --arg "hi how are you "
in this case no of arguments passed to arg how to give exception or through error if user enter above values to arg1.
function test() {
filename=$1
echo $filename
case "$2" in
a)
echo $3 >> $filename
echo "add "
# cat $filename
shift
shift
;;
exit
}
test $fileName $3 $4
argsCount here will do the trick if you want to have a check on the number of the arguments passed. In the below example, I am passing 3 arguments and validation whether the arguments counts is equal to 3, if not it will exit from the script.
#!/usr/bin/env bash
set -ex
set -o pipefail
copyConfigFrom=$1
hostConfigFileName=$2
hostnameEmail=$3
argsCount="$#"
if [ "$argsCount" -ne 3 ]; then
echo "Usage: $0 copyConfigFrom hostConfigFileName hostnameEmail"
exit 1
fi
I have a shell script as below:
$ cat check.sh
echo "$#"
for i in "$#"; do
echo "$i"
done
If I run the script with command line args, it prints as below:
$ ./check.sh arg1 arg2 "This is a message" arg4
arg1 arg2 This is a message arg4
arg1
arg2
This is a message
arg4
All is well till now.. -- the number of arguments shown are 4
If I take $# into an variable and do the same thing on it, it will behave as below:
$ cat check.sh
VARGS="$#"
echo "$VARGS"
for i in $VARGS; do
echo "$i"
done
$ ./check.sh arg1 arg2 "This is a message" arg4
arg1 arg2 This is a message arg4
arg1
arg2
This
is
a
message
arg4
Here the number of arguments are 7.
The reason that I have taken the arguments in a temp variable is to remove some unwanted args from it and pass it to another application/process.
Can someone let me know how to get the same behavior in this scenario as if we are using "$#"
Thanks for your help in advance.
I'm using ksh93 for this, but it ought to work in ksh88 as well as it also has arrays:
set -A VARGS "$#"
IFS=
for i in ${VARGS[#]}; do
echo "$i"
done
Setting IFS= is necessary, otherwise the "This is a message" string would be chopped up on spaces.
I have a simple shell script which takes 2 argument (name and age), assigns the argument to variable and prints the variable
If I pass only age value without name, the variable "vname" is assigned with age value
But I want to assign name to vname and age to vage.. In case if name is not passed them vname variable should not have any value.Can any one let me know how to implement this?
#!/bin/bash
vname=$1
vage=$2
echo $vname
echo $vage
#!/bin/bash
echo $#
#### the number $# tests the number of arguments
## you can use it to create a loop or do the following
if [[ $1 = *[[:digit:]]* ]]; then
echo " Arg1 is numeric"
# assign Arg1 to age here .... (not coding for you)
else
echo "Arg1 is not numeric"
if [[ $2 = *[[:digit:]]* ]]; then
echo " Arg2 is numeric"
else
echo "Arg2 is not numeric"
fi
fi
I saved this code as "name_and_age.sh" and ran it:
./name_and_age.sh as 2
2
Arg1 is not numeric
Arg2 is numeric
Who can simply explain
what is the difference between $* and $#?
Why there are two variables for same content as above?
There is no difference if you do not put $* or $# in quotes. But if you put them inside quotes (which you should, as a general good practice), then $# will pass your parameters as separate parameters, whereas $* will just pass all params as a single parameter.
Take these scripts (foo.sh and bar.sh) for testing:
>> cat bar.sh
echo "Arg 1: $1"
echo "Arg 2: $2"
echo "Arg 3: $3"
echo
>> cat foo.sh
echo '$* without quotes:'
./bar.sh $*
echo '$# without quotes:'
./bar.sh $#
echo '$* with quotes:'
./bar.sh "$*"
echo '$# with quotes:'
./bar.sh "$#"
Now this example should make everything clear:
>> ./foo.sh arg1 "arg21 arg22" arg3
$* without quotes:
Arg 1: arg1
Arg 2: arg21
Arg 3: arg22
$# without quotes:
Arg 1: arg1
Arg 2: arg21
Arg 3: arg22
$* with quotes:
Arg 1: arg1 arg21 arg22 arg3
Arg 2:
Arg 3:
$# with quotes:
Arg 1: arg1
Arg 2: arg21 arg22
Arg 3: arg3
Clearly, "$#" gives the behaviour that we generally want.
More detailed description:
Case 1: No quotes around $* and $#:
Both have same behaviour.
./bar.sh $* => bar.sh gets arg1, arg2 and arg3 as separate arguments
./bar.sh $# => bar.sh gets arg1, arg2 and arg3 as separate arguments
Case 2: You use quotes around $* and $#:
./bar.sh "$*" => bar.sh gets arg1 arg2 arg3 as a single argument
./bar.sh "$#" => bar.sh gets arg1, arg2 and arg3 as a separate arguments
More importantly, $* also ignores quotes in your argument list. For example, if you had supplied ./foo.sh arg1 "arg2 arg3", even then:
./bar.sh "$*" => bar.sh will still receive arg2 and arg3 as separate parameters!
./bar.sh "$#" => will pass arg2 arg3 as a single parameter (which is what you usually want).
Notice again that this difference occurs only if you put $* and $# in quotes. Otherwise they have the same behaviour.
Official documentation: http://www.gnu.org/software/bash/manual/bash.html#Special-Parameters
Aside from the difference as described in the technical documents, it is best shown using some examples:
Lets assume we have four shell scripts, test1.sh:
#!/bin/bash
rm $*
test2.sh:
#!/bin/bash
rm "$*"
test3.sh:
#!/bin/bash
rm $#
test4.sh:
#!/bin/bash
rm "$#"
(I am using rm here instead of echo, because with echo, one can not see the difference)
We call all of them with the following commandline, in a directory which is otherwise empty:
./testX.sh "Hello World" Foo Bar
For test1.sh and test3.sh, we receive the following output:
rm: cannot remove ‘Hello’: No such file or directory
rm: cannot remove ‘World’: No such file or directory
rm: cannot remove ‘Foo’: No such file or directory
rm: cannot remove ‘Bar’: No such file or directory
This means, the arguments are taken as a whole string, joined with spaces, and then reparsed as arguments and passed to the command. This is generally not helpful when forwarding arguments to another command.
With test2.sh, we get:
rm: cannot remove ‘Hello World Foo Bar’: No such file or directory
So we have the same as for test{1,3}.sh, but this time, the result is passed as one argument.
test4.sh has something new:
rm: cannot remove ‘Hello World’: No such file or directory
rm: cannot remove ‘Foo’: No such file or directory
rm: cannot remove ‘Bar’: No such file or directory
This implies that the arguments are passed in a manner equivalent to how they were passed to the the script. This is helpful when passing arguments to other commands.
The difference is subtle, but will bite you when passing arguments to commands which expect information at certain points in the command line and when spaces take part in the game. This is in fact a good example of one of the many pitfalls of most shells.
see this here :
$# Stores the number of command-line arguments that
were passed to the shell program.
$? Stores the exit value of the last command that was
executed.
$0 Stores the first word of the entered command (the
name of the shell program).
$* Stores all the arguments that were entered on the
command line ($1 $2 ...).
"$#" Stores all the arguments that were entered
on the command line, individually quoted ("$1" "$2" ...).
take an example
./command -yes -no /home/username
so now..
$# = 3
$* = -yes -no /home/username
$# = ("-yes" "-no" "/home/username")
$0 = ./command
$1 = -yes
$2 = -no
$3 = /home/username
They are different when quoted:
$ set "a b" c d
$ echo $#
3
$ set "$*"
$ echo $#
1
$ set "a b" c d
$ echo $#
3
$ set "$#"
$ echo $#
3
Here only the second form preserves the argument count.