0

I want to pass multiple arguments to a bash script as a single string parameter to an external executable (especially git)

I found several answers that suggest something like this:

"'$*'"
"'$@'"

which looks pretty good when passing to echo but fails when passed to an external programm, even if piped through echo.

This is a MWE:

#!/bin/bash

# preparation
git init .
git add -A

echo git commit -m "'$@'" # works when copied to terminal
git commit -m "'$@'" # fails if more than one parameter given
git commit -m $(echo "'$@'") # fails if more than one parameter given

rm -rf .git # c

reults in:

$ bash test.sh test2 test2
empty Git-Repository in /tests/bash-scripts/.git/ initialized
git commit -m 'test1 test2'
error: pathspec 'test2'' did not match any file(s) known to git.
error: pathspec 'test2'' did not match any file(s) known to git.

How do I pass multiple script parameters as a single string (including spaces) to an external executable (without wrapping them in "" in the script call.


Just found out that this works:

 git commit -m "$(echo "'$@'")"

but that leads me to the next level:

I want to ommit the -m parameter if no arguments are given so that the commit message editor is triggered:

if [ 0 != $# ]
then
  MESSAGE ="-m " "$(echo "'$@'")"
fi
git commit $MESSAGE

or

if [ 0 != $# ]
then
  MESSAGE =("-m " "$(echo "'$@'")")
fi
echo 
git commit ${MESSAGE[@]}

this again fails even wose, the quoted words are also separated.:

$bash test.sh "test1 test2" test3
git commit -m 'test1 test2 test3'
error: pathspec 'test2' did not match any file(s) known to git.
error: pathspec 'test3'' did not match any file(s) known to git.

1 Answer 1

5

If you want to interpret all the arguments as one string, use

"$*"

i.e.

git commit -m "$*"

It's documented in man bash under "Special Parameters":

* Expands to the positional parameters, starting from one. When the expansion is not within double quotes, each positional parameter expands to a separate word. In contexts where it is performed, those words are subject to further word splitting and pathname expansion. When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable. That is, "$*" is equivalent to "$1c$2c...", where c is the first character of the value of the IFS variable. If IFS is unset, the parameters are separated by spaces. If IFS is null, the parameters are joined without intervening separators.

5
  • thanks for your answer. it solves the first problem, but not the second after my update. Feb 7, 2020 at 9:42
  • message=(-m "$*") should work.
    – choroba
    Feb 7, 2020 at 10:33
  • no, it does not MESSAGE=(-m "$*") followed by echo git commit ${MESSAGE[@]} results in git commit -m test1 test2 test3 which misses the quotes around the parameters and therefore fails when omitting the echo. Feb 7, 2020 at 11:39
  • 1
    You need to doublequote: git commit "${message[@]}".
    – choroba
    Feb 7, 2020 at 11:43
  • 1
    @TimothyTruckle you really need to read mywiki.wooledge.org/Quotes as knowing which type of quotes to use where/when is crucial when writing shell scripts. Also run all of your programs through shellcheck.net until you get more experience.
    – Ed Morton
    Feb 9, 2020 at 0:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .