368

What does a dollar sign followed by an at-sign (@) mean in a shell script?

For example:

umbrella_corp_options $@
Henk Langeveld
  • 8,088
  • 1
  • 43
  • 57
trusktr
  • 44,284
  • 53
  • 191
  • 263

8 Answers8

419

$@ is all of the parameters passed to the script.

For instance, if you call ./someScript.sh foo bar then $@ will be equal to foo bar.

If you do:

./someScript.sh foo bar

and then inside someScript.sh reference:

umbrella_corp_options "$@"

this will be passed to umbrella_corp_options with each individual parameter enclosed in double quotes, allowing to take parameters with blank space from the caller and pass them on.

Andrea Bergonzo
  • 3,983
  • 4
  • 19
  • 31
Har
  • 4,864
  • 2
  • 19
  • 22
  • 2
    What would $@ contain if I did `someScript.sh foo bar "boo far"`? – trusktr Apr 03 '12 at 14:02
  • 2
    http://teaching.idallen.com/dat2330/04f/notes/shell_variables.txt Check this out. – Har Apr 03 '12 at 14:13
  • 11
    $@ is special if written in double quotes. Then it will result in a list of quoted values, in your case, trusktr, in the three arguments "foo", "bar", and "boo far". – Alfe Apr 03 '12 at 14:28
  • 5
    Although it is generally the case, `$@` does *not necessarily* come from paramaters passed to the script... eg; `set a b "x   y"; printf '(%s)' "$@"` outputs `(a)(b)(x   y)` – Peter.O Apr 03 '12 at 14:37
  • 4
    I like Alfe's answer better because he gives the main difference between `$@` and `$*` – donleyp Nov 30 '17 at 04:41
  • 2
    Small nitpick: there is the implicit parameter `$0`. `$@` is all parameters from `$1` onwards – Roland Jun 20 '20 at 15:15
198

$@ is nearly the same as $*, both meaning "all command line arguments". They are often used to simply pass all arguments to another program (thus forming a wrapper around that other program).

The difference between the two syntaxes shows up when you have an argument with spaces in it (e.g.) and put $@ in double quotes:

wrappedProgram "$@"
# ^^^ this is correct and will hand over all arguments in the way
#     we received them, i. e. as several arguments, each of them
#     containing all the spaces and other uglinesses they have.
wrappedProgram "$*"
# ^^^ this will hand over exactly one argument, containing all
#     original arguments, separated by single spaces.
wrappedProgram $*
# ^^^ this will join all arguments by single spaces as well and
#     will then split the string as the shell does on the command
#     line, thus it will split an argument containing spaces into
#     several arguments.

Example: Calling

wrapper "one two    three" four five "six seven"

will result in:

"$@": wrappedProgram "one two    three" four five "six seven"
"$*": wrappedProgram "one two    three four five six seven"
                             ^^^^ These spaces are part of the first
                                  argument and are not changed.
$*:   wrappedProgram one two three four five six seven
Alfe
  • 56,346
  • 20
  • 107
  • 159
  • 4
    They are *not* the same, and the manpage is clear on the side-effects of $* using IFS—which is not necessarily space. (If they were the same, there would not be any point, other than compatibility perhaps, in offering both.) – jørgensen Apr 03 '12 at 14:48
  • 11
    No they are not. And I said so two lines below: "The difference between the two ..." In order to get short sentences and raise readability the reader has to read more than one sentence before giving a verdict :-/ – Alfe Apr 05 '12 at 15:41
  • 3
    Alfe, Christoffer's insertion of that one word "nearly" made a hell of a difference, without sacrificing any terseness or readability. In fact I upvoted this answer (as opposed to the accepted one) exactly due to that subtle emphasis of the *difference*... -- before realizing that it was almost against your will! ;) – Sz. Mar 02 '17 at 13:13
  • I think that word made a hell of a difference for the people who give a verdict right after reading the first sentence ;-) and it was never against my will. I would really like to write also for these people. – Alfe Mar 02 '17 at 17:54
  • Very unclear. `wrappedProgram "$*"` -> `separated by single spaces.` but in your 2nd example they aren't separated by single spaces. – Felix Dombek Apr 04 '18 at 13:50
  • Yes they are. But the first parameter *contains* multiple spaces which are untouched. I will add this aspect to my text. – Alfe Apr 04 '18 at 13:55
  • Why do you skip out the example of $@ without quotes? You gave $* with and without quotes. Why not for $@ ? – barlop May 12 '20 at 03:35
  • @barlop Because `$@` without quotes isn't useful. If it appears, it typically is just an error and the version with quotes was intended. Without the quotes it does the same as `$*` without quotes (which is consequent, but, as I said, useless). – Alfe May 18 '20 at 01:52
65

These are the command line arguments where:

$@ = stores all the arguments in a list of string
$* = stores all the arguments as a single string
$# = stores the number of arguments

Jonatas Walker
  • 13,583
  • 5
  • 53
  • 82
Sameer Duwal
  • 651
  • 5
  • 2
18

The usage of a pure $@ means in most cases "hurt the programmer as hard as you can", because in most cases it leads to problems with word separation and with spaces and other characters in arguments.

In (guessed) 99% of all cases, it is required to enclose it in ": "$@" is what can be used to reliably iterate over the arguments.

for a in "$@"; do something_with "$a"; done
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • 5
    Your line can be written as: for a; do something_with "$a"; done ;-) – Alfe Apr 03 '12 at 14:11
  • 1
    @Alfe I know;I just hat forgotten it. Think of it as `for a in start_token "$@" end_token; do something_with "$a"; done` :-) – glglgl Apr 03 '12 at 14:39
16

Meaning.

In brief, $@ expands to the arguments passed from the caller to a function or a script. Its meaning is context-dependent: Inside a function, it expands to the arguments passed to such function. If used in a script (outside a function), it expands to the arguments passed to such script.

$ cat my-script
#! /bin/sh
echo "$@"

$ ./my-script "Hi!"
Hi!
$ put () { echo "$@"; }
$ put "Hi!"
Hi!

* Note: Word splitting.

The shell splits tokens based on the contents of the IFS environment variable. Its default value is \t\n; i.e., whitespace, tab, and newline. Expanding "$@" gives you a pristine copy of the arguments passed. Expanding $@ may not. More specifically, any arguments containing characters present in IFS might split into two or more arguments or get truncated.

Thus, most of the time what you will want to use is "$@", not $@.

Luis Lavaire.
  • 599
  • 5
  • 17
12

From the manual:

@

Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$@" is equivalent to "$1" "$2" .... If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word. When there are no positional parameters, "$@" and $@ expand to nothing (i.e., they are removed).

Community
  • 1
  • 1
Christoffer Hammarström
  • 27,242
  • 4
  • 49
  • 58
-1

$@ is basically use for refers all the command-line arguments of shell-script. $1 , $2 , $3 refer to the first command-line argument, the second command-line argument, third argument.

Shubh Patel
  • 87
  • 1
  • 6
-2

They are often used to simply pass all arguments to another program

[root@node1 shell]# ./my-script hi 11 33 hi 11 33 [root@node1

王传义
  • 45
  • 1