Alex Alex - 20 days ago 5
Git Question

Bash $@ and $* string handling

In my .bashrc file I have a function that at some some point needs to call git and pass to it all the parameters received. What I did is:

git $*


but when passing a string as a parameter, this is treated like there were no quotes.

When typing
myfunction commit -m "More than a word"
, an
echo "git $*"
from inside the function gives
git commit -m More that a word
, so I tried calling it with escape characters as follows:

myfunction commit -m \"More than a word\"


which correctly expands to
git commit -m "More than a word"
, but I still get the same errors:

error: pathspec 'than' did not match any file(s) known to git.
error: pathspec 'a' did not match any file(s) known to git.
error: pathspec 'word"' did not match any file(s) known to git.


How can I pass any parameter in a correct way? Also, what's actually happening?

Answer

On $* and $@

Your function should use:

git "$@"

...with the quotes.


  • $* expands to a single string containing all arguments separated by the first character of $IFS, by default a space. The result is then split on all characters in IFS into multiple words, and each of those words is evaluated as a glob.
  • "$*" expands to a single string containing all arguments separated by the first character of $IFS, and is not subsequently split into globbed pieces.
  • $@ is identical to (unquoted) $*.
  • "$@" expands to the precise argument vector given to your function.

On \"\" vs ""

When quotes are escaped, they become literal rather than syntactic. This means that they no longer serve their syntactic purpose, but are data, treated as any other data would be.

Consequently:

printf '%s\n' \"hello world\"

...is entirely correct to emit:

"hello
world"