Pass arguments to function exactly as-is

Use "$@":

$ bar() { echo "$1:$2"; }
$ foo() { bar "$@"; }
$ foo "This is" a test
This is:a

"$@" and "$*" have special meanings:

  • "$@" expands to multiple words without performing expansions for the words (like "$1" "$2" ...).
  • "$*" joins positional parameters with the first character in IFS (or space if IFS is unset or nothing if IFS is empty).

You must use $@, instead of $*

bar() { echo "$1:$2"; }

foo() { bar "$@"; }

foo "This is" a test

ouput

This is:a

Why does it work?

Because with $*, all parameter is seen as a single word, it mean that you will pass This is a test to bar function. In this case, the 1st parameter pass to function bar is This, 2nd is is.

With $@, each parameter is a quoted string, it mean that you will pass 'This is' 'a' 'test' to bar funtion. So the 1st parameter pass to function bar is This is, 2nd is a.