Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bourne shell: send arguments $2 to $N to variadic function?

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?

like image 995
chpatton013 Avatar asked Aug 17 '12 09:08

chpatton013


People also ask

How do you pass an argument to a shell function?

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.

How do you pass an argument to a function in bash?

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 …


3 Answers

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
like image 102
Quadturtle Avatar answered Oct 05 '22 16:10

Quadturtle


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:

  • bash — being space safe when saving in a variable
  • ${1:+"$@"} in /bin/sh
like image 30
Jonathan Leffler Avatar answered Oct 05 '22 15:10

Jonathan Leffler


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.

like image 28
William Pursell Avatar answered Oct 05 '22 17:10

William Pursell