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?

1
  • 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
    Commented Jan 26, 2019 at 2:18

1 Answer 1

10

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.

It rarely makes sense to use $* or $@ unquoted.

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

set -- "bumblebee 1" "bumblebee 2"
IFS=,

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$IFS$2" here
0

You must log in to answer this question.

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