8

Can someone explain to me in a concise way what the difference between these two vars is?

What is the safest way to pass variables to another program?

E.g.

#! /bin/bash

# do stuff

# pass variables onto another program
java $@
0

3 Answers 3

13

Using this script:

#! /bin/sh
# Greg Wooledge's args script
printf "%d args:" $#
printf " <%s>" "$@"
echo

Try this demo:

$ set -- a 'b     c' d
$ args $*
4 args: <a> <b> <c> <d>
$ args $@
4 args: <a> <b> <c> <d>
$ args "$*"
1 args: <a b     c d>
$ args "$@"
3 args: <a> <b     c> <d>

You should usually use "$@" (with the quotes).

Sometimes it's useful to change IFS and use "$*":

$ saveIFS=$IFS; IFS='|'; args "$*"; IFS=$saveIFS
1 args: <a|b     c|d>
5

safest is "$@" because it passes the arglist on without expansion and separates each argument. See http://www.faqs.org/docs/abs/HTML/variables2.html#ARGLIST for more detail.

2
  • 1
    You mean literally "$@" (with quotes), yes?
    – Jonathan
    Commented Mar 18, 2011 at 20:59
  • @Jonathan: Yes, literally (with quotes). If the double quotes are not present, then the value of each positional parameter in $@ will undergo word-splitting (based on the contents of IFS) and pathname expansion (“globbing” aka wildcards: *, ?, []). Commented Mar 19, 2011 at 5:28
5

Use: "$@" if you want to represent the original arguments (including no arguments) accurately.

There are 5 notations to mention:

  • $@
  • $*
  • "$@"
  • "$*"
  • ${1+"$@"}

The first two are equivalent; both split up the words in the argument list and pass them on to the command being invoked. They are seldom the correct choice.

The second two are radically different. The "$@" notation effectively copies the arguments to the shell (or the arguments set via the set command) to the command being invoked, preserving the number of arguments, the spaces within them, and the split between them. If there are zero arguments, it generates nothing.

The "$*" notation pastes all the arguments into a single string, putting a space between arguments but preserving the spaces within the arguments. It is appropriate for use in contexts such as:

echo "You said, '$*'"

where the utmost fidelity to the original command line is not crucial.

The final notation, ${1+"$@"}, is a hangover from days past that you may come across in old shell scripts. Once upon a time (and a long time ago - like 30 years ago), the Bourne shell treated "$@" as a single empty argument when there were no arguments. That has not been the behaviour for a long time, but some scripts written a very long time ago might still protect themselves by using this notation. The ${1+X} notation means 'if $1 is set to anything, even an empty string, then provide the value X. In the notation under discussion, the X is "$@", which is a list of arguments when there is known to be at least one - and otherwise no arguments. Which means the same as "$@" in any modern shell.

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