1

I've got a script that takes a variable number of parameters. I also have a wrapper script where I take the same parameters and add some more. The problem is that when I have params with spaces they get split by words when passed to the "inside" script.

For example the outside script:

# tst1.sh

echo "-- tst1.sh --"
echo "1: $1"
echo "2: $2"

./tst2.sh $* --some --more --params

And the inside script:

#!/bin/bash

echo "-- tst2.sh --"
echo "1: $1"
echo "2: $2"

Now when I call the wrapper script it gets the date correct as a single parameter, however the inside one only gets the first word:

$ ./tst1.sh --date "$(date)"
-- tst1.sh --
1: --date
2: Fri Jan 25 21:51:57 GMT 2019

-- tst2.sh --
1: --date
2: Fri                            <== this is wrong

I want the output of the second script the same as the first one. And all that for a variable number of parameters, that's why I use $* and not individual $1, $2, etc that I could quote.

I tried quoting "$*" but that then joins the --date and the actual date string as a single parameter.

Any idea how to do that?

  • Another approach would be to use zsh instead of bash. Handling this particular situation with less direction from the programmer is one of its better features. However, it is still a shell, so you still need to keep quoting in mind to some extent more than in more formal scripting languages. – Ed Grimm Jan 26 at 2:18
7

Use "$@":

./tst2.sh "$@" --some --more --params

The difference between $* and "$@" is that $* will be a single string consisting of the concatenation of all the positional parameters with the first character of $IFS as delimiter (this string would additionally undergo word-splitting and filename expansion since it's unquoted), while "$@" (note the double quotes!) will be each positional parameter individually quoted.

When wanting to preserve the individual positional parameters, always use "$@".

When wanting to join the positional parameters on the first character of $IFS to create a single string, use "$*". This is rarely used apart from when creating text strings under some circumstances.

Short example of "$@" vs. "$*":

set -- "bumblebee 1" "bumblebee 2"

printf 'With "$@": %s\n' "$@"
printf 'With "$*": %s\n' "$*"

Output (with added annotations)

With "$@": bumblebee 1               <-- "$1" here
With "$@": bumblebee 2               <-- "$2" here
With "$*": bumblebee 1 bumblebee 2   <-- "$1 $2" here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.