I am writing a bash script that takes in some optional parameters. I want to translate them and pass them to another script. However, I'm having a hard time passing the optional parameters gracefully.
Here's a outline of what I managed to get working in pseudocode:
a.sh:
if arg1 in arguments; then
firstArg="first argument"
fi
if arg2 in arguments; then
secondArg="second argument"
fi
./b.sh $firstArg $secondArg "default argument"
Note the spaces in the arguments.
b.sh:
for arg in "$@"
do
echo $arg
done
I want to call b.sh
, optionally with firstArg
and secondArg
and a default argument like so:
./b.sh $firstArg $secondArg "default argument"
The problem with this is that if $firstArg
or $secondArg
are strings with spaces, they will be represented as multiple arguments, and the output will be something like:
first
argument
second
argument
default argument
Okay, that's easy to fix, let's capture the entire string of the arguments by adding quotes around it like so:
./b.sh "$firstArg" "$secondArg" "defaultArg"
Problem is if, for example, firstArg
is not set, it results in a blank line (as it will interpret ""
as a parameter), so the output will be something like:
(blank line here)
second argument
defaultArg
I've also tried constructing a string and passing it to the shell script, but it doesn't seem to work that way either (it interprets the whole string as an argument, even if I add separate the arguments with quotes).
Note that calling b.sh
from my command line with the arguments quoted works fine. Is there a way to mimic how this works from within a bash script?
We can use the getopts program/ command to parse the arguments passed to the script in the command line/ terminal by using loops and switch-case statements. Using getopts, we can assign the positional arguments/ parameters from the command line to the bash variables directly.
The ability to process options entered at the command line can be added to the Bash script using the while command in conjunction with the getops and case commands. The getops command reads any and all options specified at the command line and creates a list of those options.
Here for the [Optional] attribute is used to specify the optional parameter. Also, it should be noted that optional parameters should always be specified at the end of the parameters. For ex − OptionalMethodWithDefaultValue(int value1 = 5, int value2) will throw exception.
If you literally want to copy all arguments given, but add one more:
# this works in any POSIX shell
./b.sh "$@" defaultArg
Alternately, to explicitly pass firstArg
and secondArg
, but only if they exist (note that set-to-an-empty-value counts as "existing" here):
# this works in any POSIX shell
./b.sh ${firstArg+"$firstArg"} ${secondArg+"$secondArg"} defaultArg
If you want to treat set-to-an-empty-value as not existing:
# this works in any POSIX shell
./b.sh ${firstArg:+"$firstArg"} ${secondArg:+"$secondArg"} defaultArg
An alternate approach is to build up an array of arguments:
# this requires bash or another shell with arrays and append syntax
# be sure any script using this starts with #!/bin/bash
b_args=( )
[[ $firstArg ]] && b_args+=( "$firstArg" )
[[ $secondArg ]] && b_args+=( "$secondArg" )
b_args+=( "default argument" )
./b.sh "${b_args[@]}"
If you want something with the same flexibility as the array method, but without the compatibility issues, define a function; within it, you can safely override "$@"
without impacting the rest of the script:
runB() {
set --
[ -n "$firstArg" ] && set -- "$@" "$firstArg"
[ -n "$secondArg" ] && set -- "$@" "$secondArg"
./b.sh "$@" "default argument"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With