Google has finally failed me. I cannot seem to find how to do this in Bourne shell scripting:
I am writing a shell script to handle all of my testing for a project. I've set up functions for each task that this script could do (build, run, clean, etc), and would like to pass any additional command-line parameters (besides the command itself) onto the desired function.
Example:
./test.sh build -j
should pass -j
into the build
function.
A pseudo-code version of this logic would look like:
function build() {
make $*
}
if [ $1 == 'build' ]; then
build $2 -> $N
fi
How can I accomplish this?
To invoke a function, simply use the function name as a command. To pass parameters to the function, add space separated arguments like other commands. The passed parameters can be accessed inside the function using the standard positional variables i.e. $0, $1, $2, $3 etc.
To pass any number of arguments to the bash function simply put them right after the function's name, separated by a space. It is a good practice to double-quote the arguments to avoid the misparsing of an argument with spaces in it. The passed parameters are $1 , $2 , $3 …
I think you could achieve this effect using the shift
command. It will move all of the positional parameters down one place and drops the value of $1
(so the value of $3
gets moved to $2
, the value of $2
gets moved to $1
and the value of $1
is lost). Once you've done that you can just use $@
to pick up the list of arguments you're actually interested in e.g.
function build() {
echo "build with $@"
}
echo "Starting args are $@"
cmd=$1
shift
if [ "$cmd" = 'build' ]; then
build "$@"
fi
function build() {
make "$@"
}
if [ "$1" == 'build' ]
then shift # Lose $1
build "$@" # Pass what was $2 .. $N
fi
Note the use of "$@"
both in the function itself and in the invocation of the function. I would argue that it is seldom correct to use either $*
or $@
without the double quotes or "$*"
; only "$@"
preserves the spacing of the original argument list, which matters if you have arguments that contains spaces. If you're going to echo the arguments, then echo "The arguments: $*"
is reasonable. Otherwise, more than 90% of the time, you'd be better off using "$@"
. I also take an extremely conservative attitude towards quoting "$1"
in the test operator; be cautious about omitting the quotes.
See also:
Unless you are wanting to emit a more detailed error message, there's no need to test $1
explicitly. Just do:
#!/bin/sh -e
function build() {
make "$@"
}
"$@"
If $1
names a valid function, it will be called as desired. If it does not, you'll get an error message which is probably not too bad, depending on your shell.
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