12

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?

chpatton013
  • 363
  • 1
  • 5
  • 11

3 Answers3

19

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
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
Quadturtle
  • 206
  • 2
  • 2
5
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:

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
2

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.

William Pursell
  • 204,365
  • 48
  • 270
  • 300