9

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
  • 333
  • 4
  • 10

3 Answers3

16

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'
  • 98,216
  • 36
  • 202
  • 244
Quadturtle
  • 176
  • 1
  • 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
  • 698,132
  • 130
  • 858
  • 1,229
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
  • 190,037
  • 45
  • 260
  • 285