2

Recently I was learning bash commands in Linux, specifically string manipulation. In that there was a local variable declared to be equal to ${@}. I understand that $n refers to the nth command line argument provided to the command. But what is the meaning of ${@}?

The command given was:

local instr;
instr="${@}";
AdminBee
  • 22,803
  • The two duplicate targets between them should explain this well enough: $@ is the array of positional parameters, ${@} is equivalent to $@. – terdon Jul 27 '21 at 09:27

1 Answers1

4

In Bash (and all POSIX-like shells), $@ or ${@} is a "special parameter" that expands to a list of all positional parameters (= command-line arguments). It is in that respect similar to $*, but with the addition that it can be double-quoted to expand to a list of individual tokens rather than one string containing all positional parameters separated by spaces(1).


(1) Actually, the arguments are not joined explicitly by "space", but rather by the first character of $IFS, the input field-separator variable, which however defaults to "space" in many shells. In the further text I will still use "space" for simplicity and assume that either you left $IFS at its default or changed it to your needs but know what you do.


So,

  • "$*" is equivalent to "$1 $2 $3 ... " and would be treated as "one word" whereas
  • "$@" is equivalent to "$1" "$2" "$3" ... and would be treated as "several individual words".

Without quotes, both would simply be a space-separated list of words. The difference becomes important when the command-line arguments themselves are strings with spaces, as in

./my_script.sh parameter1 parameter2 "a whole sentence as parameter"
  • $* or $@ without quotes would expand to a list of seven individual tokens. This is rarely what you want.
  • "$*" would expand to one token consisting of seven space-separated words (parameter1 parameter2 a whole sentence as parameter). This is in most cases not what you want.
  • "$@" would expand to a list of 3 tokens, the first two being parameter1 and parameter2, and the last being the string a whole sentence as parameter including its spaces. This is what you will want in most cases, in particular when you want to use it as a list of tokens (to iterate over, to assign to an array, or to pass to a self-defined function).

For further reading, in particular concerning the subtleties of shell variable quoting and word splitting, I would refer you to

ilkkachu
  • 138,973
AdminBee
  • 22,803
  • So if I define a function which takes 1 parameter, and then call the function with my argument as "$@", then it will pass each command line argument one-by-one to the function, so in effect I'm reusing the function on the arguments in a single program? – Ash Ketchum Jul 27 '21 at 09:29
  • @AshKetchum perhaps the edit makes that point clearer. In your case, if your function takes only one argument (meaning that in the function code you only ever reference $1), passing "$@" to the function would make the function take only the first of the command-line parameters. The $@ and $* really only expand to a list, the do not automatically imply looping over the list. – AdminBee Jul 27 '21 at 09:37
  • Hm, I'm not sure what to think of the terminology used in this answer... I mean, you're using "word" in the natural language meaning, and "token" for the thing that eventually ends up as a distinct argument to the program, which does make sense, but the problem is that e.g. Bash's manual uses "word" to mean the latter (i.e. "foo bar" is one shell word), and on the other hand, "token" is used for a unit of parsing, e.g. words are tokens, but so are operators like ( and ||. – ilkkachu Jul 27 '21 at 11:47
  • @ilkkachu That's true. The difficulty in formulating the answer is that the OP is obviously rather new to shell scripting, so I thought using the more "intuituve" formulation might be better. I agree though, that this creates an unfortunate conflict with established terminology. Maybe if I have the time to think about it I can find a solution to that... – AdminBee Jul 27 '21 at 11:51
  • 1
    AdminBee, yep. If anyone comes up with a good way to discuss this, please tell me too. :) Using "shell word" might be clearer than just "word", but I think I've used "argument" too (like Stéphane above), but then something in my brain nags about that too, that the words don't become arguments until they're given to the command to run... But please don't mind my rambling, I mostly just wanted to note that if e.g. @AshKetchum or someone goes on to read the manual, the terminology there will be different. – ilkkachu Jul 27 '21 at 12:04