2

From the bash man page:

"$*" is equivalent to "$1c$2c...", where c is the first character of the value of the IFS variable.

"$@" is equivalent to "$1" "$2" ...

Any example where "$@" cannot work in place of "$*"?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Deepak
  • 575
  • 1
  • 5
  • 13

3 Answers3

5

My favorite use is replacing the field separator.

$ set -- 'My word' but this is a bad 'example!'
$ IFS=,
$ echo "$*"
My word,but,this,is,a,bad,example!

There are other ways to replace delimiters, but IFS and "$*" are often one of the simplest.

kojiro
  • 74,557
  • 19
  • 143
  • 201
  • 2
    Indeed. I often use `printf -v output '%s,' "$@"` for the same task, but that leaves a trailing `,` that needs to be stripped (though `output=${output%,}` makes short work of it, that's not exactly pretty). – Charles Duffy May 06 '15 at 17:08
4

These are completely different tools and should be used in completely different situations. There's no reasonable question about one substituting for the other, because in any given situation, only one or the other will be correct.

"$*" is most applicable when you're trying to form a single string argument from an argument list -- mostly for logging (but not cases where division between arguments is important; then, "$@" is appropriate with something like print '%q '). "$@" is useful in... well, any other case.

Examples:

die() {
    local stat=$1; shift
    log "ERROR: $*"
    exit $stat
}

Using "$*" when formatting a string to be passed to log uses only a single argv entry, allowing other optional positional arguments to be added to log's usage in the future.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 2
    I think another way to put it would be, "The only time one can do the other's job is when both are being used incorrectly." – kojiro May 06 '15 at 17:02
1

$* expands to all parameters as just one word with IFS between parameters.

$@ expands to all parameters as a list.

Try next code in a file named list.sh:

#!/bin/bash

echo "using '$*'"
for i in "$*"
do
    echo $i
done

echo "using '$@'"
for i in "$@"
do
    echo $i
done

use it:

./list.sh apple pear kiwi
  • 1
    The OP clearly knows this already -- their question isn't how the two differ, but what practical use `$*` is given the availability of `$@`. – Charles Duffy May 06 '15 at 17:09
  • (BTW, as a point on correctness, `echo "$i"` would be better than `echo $i`; otherwise, globs would be expanded, runs of whitespace compressed, etc; one might make additional improvement by using `printf '%s\n' "$i"` instead, which would correct handling with arguments such as `-n` that `echo` would otherwise consume itself). – Charles Duffy May 06 '15 at 17:13