How to write a very simple wrapper that provides default parameters?
Solution 1
A default value is easy to define in Bash:
foo="${bar-default}" # Sets foo to the value of $bar if defined, "default" otherwise
foo="${bar:-default}" # Sets foo to the value of $bar if defined or empty, "default" otherwise
To process your parameters, you can use a simple loop:
while true
do
case "${1-}" in
-in)
infile="${2-}"
shift 2
;;
-out)
outfile="${2-}"
shift 2
;;
*)
break
;;
esac
done
program -in "${infile-otherfile}" -out "${outfile-otherout}" "$@"
Useful reads:
I also recommend using getopt
instead, because it is able to handle many special cases which would very quickly complicate and clutter your code (Non-trivial example).
Solution 2
l0b0's answer shows how to set a default value through assignment and checking another variable's state (although, of course, you can also do this operating on the same variable you are assigning to), but there is a more concise way to do the same thing:
: "${foo=bar}" # $foo = bar if $foo is unset
: "${foo:=bar}" # $foo = bar if $foo is unset or empty
Solution 3
You have two ways, as usual, simple and hard. Simple is to use inner variables, for example
program -in otherfile -out file.out
Here variable are
$0 = The script name
$1 = -in
$2 = otherfile, etc.
The Hard way is to use getopt
, more information you can find here.
Solution 4
- Pass all parameters (
$*
) passed toscript
toprogram
too - Check each parameter you interested, if it's already in parameters passed, then ignore it. otherwise use default parameter value
Sample code
interested_parameter_names=(-in -out)
default_parameter_values=(file.in file.out)
program=echo
cmd="$program $*"
for ((index=0; index<${#interested_parameter_names[*]}; index++))
do
param="${interested_parameter_names[$index]}"
default_value="${default_parameter_values[$index]}"
if [ "${*#*$param}" == "$*" ] # if $* not contains $param
then
cmd="$cmd $param $default_value"
fi
done
echo "command line will be:"
echo "$cmd"
echo
echo "execute result:"
$cmd
You can easily add more default parameters/values by add more array element in $interested_parameter_names
and $default_parameter_values
Sample output
$ ./wrapper.sh -in non-default.txt -other-params
command line will be:
echo -in non-default.txt -other-params -out file.out
execute result:
-in non-default.txt -other-params -out file.out
Note
When passing parameters which contains space, it should be escaped by \
, not just quoted them. Example:
./script -in new\ document.txt
Related videos on Youtube
Comments
-
Tobias Kienzler almost 2 years
Given a program that requires some parameters, e.g.
program -in file.in -out file.out
, what would be the simple-most approach to write a bash script that could be called with or without any of these parameters and use default values for each?script -in otherfile
would runprogram -in otherfile -out file.out
,
script -out otherout -furtherswitch
would runprogram -in file.in -out otherout -furtherswitch
etc. -
Tobias Kienzler over 11 yearsUsing
$1
etc will fail if I omit parameters, and manually parsing them would be annoying. Is there no midway between that and getopt? -
Tobias Kienzler over 11 yearsThanks! A
while $# -gt 0
(or similar) and*) others="${others-} $1"; shift 1 ;;
would survive other parameters before the default-able ones. But maybe I should learngetopt
instead... -
Tobias Kienzler over 11 yearsNeat! I think the quotes issue can be solved by using
$@
instead of$*
. What does${*#*$param}
do? -
Tobias Kienzler over 11 yearsOf course I could also simply write a python script...
-
LiuYan 刘研 over 11 years@TobiasKienzler,
"${*#*$param}" == "$*"
is used to check if$*
NOT contains$param
, it's Remove Smallest Prefix Pattern parameter expansion. -
Stéphane Chazelas over 11 years
./script -in new\ document.txt
would not work, and there's not way to make it work with that flawed approach. By concatenating the arguments into a string, you're losing the information about how those arguments are separated.