69

In shell scripts, what is the difference between $@ and $*?

Which one is the preferred way to get the script arguments?

Are there differences between the different shell interpreters about this?

codeforester
  • 39,467
  • 16
  • 112
  • 140
nicoulaj
  • 3,463
  • 4
  • 27
  • 32
  • From: https://www.shellscript.sh/variables2.html ,The variable $@ is all parameters $1 .. whatever. The variable $*, is similar, but does not preserve any whitespace, and quoting, so "File with spaces" becomes "File" "with" "spaces". – Channa Jan 25 '20 at 17:20

3 Answers3

78

From here:

$@ behaves like $* except that when quoted the arguments are broken up properly if there are spaces in them.

Take this script for example (taken from the linked answer):

for var in "$@"
do
    echo "$var"
done

Gives this:

$ sh test.sh 1 2 '3 4'
1
2
3 4

Now change "$@" to $*:

for var in $*
do
    echo "$var"
done

And you get this:

$ sh test.sh 1 2 '3 4'
1
2
3
4

(Answer found by using Google)

Community
  • 1
  • 1
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 18
    `"$*"` has one other interesting property. Each argument is separated by the value `$IFS` instead of a space. – R Samuel Klatchko May 03 '10 at 23:29
  • 2
    It may be worthwhile to explain how the substitutions end up expanded (what the commands look-like afterwards) and why it results in the differing results. – Bert F May 03 '10 at 23:56
23

A key difference from my POV is that "$@" preserves the original number of arguments. It's the only form that does. For that reason it is very handy for passing args around with the script.

For example, if file my_script contains:

#!/bin/bash

main()
{
   echo 'MAIN sees ' $# ' args'
}

main $*
main $@

main "$*"
main "$@"

### end ###

and I run it like this:

my_script 'a b c' d e

I will get this output:

MAIN sees 5 args

MAIN sees 5 args

MAIN sees 1 args

MAIN sees 3 args

Art Swri
  • 2,799
  • 3
  • 25
  • 36
  • Pls, can you explain the 3rd output? – Agrover112 Apr 29 '22 at 16:47
  • 1
    I assume you mean the one that encloses the dollarsign and star inside the double quotes. The double quotes 'gather' the args into a single string, namely 'a b c d e'. In addition the double quotes allow the evaluation of the dollarsign+star. (If you use single quotes around the dollarsign+star, you will get just the literal value '$*' - the shell will not expand the dollarsign+star expression. – Art Swri Apr 29 '22 at 21:33
  • I suggest you run the script, adding 5 lines (for $1, $2, ...$5) like the following to print the args seen by the main function: echo ' $1 is ' $1 – Art Swri Apr 29 '22 at 21:34
1

With $@ each parameter is a quoted string. Otherwise it behaves the same.

See: http://tldp.org/LDP/abs/html/internalvariables.html#APPREF

Gavin H
  • 10,274
  • 3
  • 35
  • 42
  • "Is a quoted string"? That implies that using `"$@"` first generates a quoted string, and then that the shell then parses it on deciding how to run the next command. It would be more accurate to say that the string concatenation done by `$*` is skipped, as is the string-splitting done when `$*` is used unquoted. Thus, using `"$@"` is not only usually more correct, but it also is less work for the shell to interpret. – Charles Duffy May 07 '12 at 23:01
  • 2
    ...by the way, to quote `!abs` in irc://irc.freenode.org/#bash -- The infamous "Advanced" Bash Scripting Guide should be avoided unless you know how to filter out the junk. It will teach you to write bugs, not scripts. In that light, the BashGuide was written: http://mywiki.wooledge.org/BashGuide – Charles Duffy May 07 '12 at 23:05