What is the difference between $ * and $@

Who can just explain

  • What is the difference between $ * and $@ ?
  • Why are there two variables for the same content as above?
+7
linux unix shell
source share
4 answers

In addition to the differences described in the technical documents, it is best to use a few examples:

Suppose we have four shell scripts, test1.sh :

 #!/bin/bash rm $* 

test2.sh :

 #!/bin/bash rm "$*" 

test3.sh :

 #!/bin/bash rm $@ 

test4.sh :

 #!/bin/bash rm " $@ " 

(I use rm here instead of echo , because there is no difference with echo )

We call all of them with the following command line in a directory that is otherwise empty:

 ./testX.sh "Hello World" Foo Bar 

For test1.sh and test3.sh we get the following output:

 rm: cannot remove 'Hello': No such file or directory rm: cannot remove 'World': No such file or directory rm: cannot remove 'Foo': No such file or directory rm: cannot remove 'Bar': No such file or directory 

This means that the arguments are taken as a whole string, combined with spaces, and then redrawn as arguments and passed to the command. This is usually not useful when passing arguments to another command.

With test2.sh we get:

 rm: cannot remove 'Hello World Foo Bar': No such file or directory 

So, we have the same thing as for test{1,3}.sh , but this time the result is passed as one argument.

test4.sh has something new:

 rm: cannot remove 'Hello World': No such file or directory rm: cannot remove 'Foo': No such file or directory rm: cannot remove 'Bar': No such file or directory 

This means that the arguments are passed in a manner equivalent to how they were passed in the script. This is useful when passing arguments to other commands.

The difference is subtle, but it will bite you when passing arguments to teams that expect information at specific points on the command line and when spaces are involved in the game. This is actually a good example of one of the many pitfalls of most shells.

+7
source share

It makes no difference if you do not quote $* or $@ . But if you put them in quotation marks (which follows, as a general good practice), then $@ will pass your parameters as separate parameters, while $* will just pass all the parameters as one parameter.

Take these scripts ( foo.sh and bar.sh ) for testing:

 >> cat bar.sh echo "Arg 1: $1" echo "Arg 2: $2" echo "Arg 3: $3" echo >> cat foo.sh echo '$* without quotes:' ./bar.sh $* echo ' $@ without quotes:' ./bar.sh $@ echo '$* with quotes:' ./bar.sh "$*" echo ' $@ with quotes:' ./bar.sh " $@ " 

Now this example should make everything clear:

 >> ./foo.sh arg1 "arg21 arg22" arg3 $* without quotes: Arg 1: arg1 Arg 2: arg21 Arg 3: arg22 $@ without quotes: Arg 1: arg1 Arg 2: arg21 Arg 3: arg22 $* with quotes: Arg 1: arg1 arg21 arg22 arg3 Arg 2: Arg 3: $@ with quotes: Arg 1: arg1 Arg 2: arg21 arg22 Arg 3: arg3 

Clearly, " $@ " gives the behavior that we usually want.


Detailed description:

Case 1: there are no quotes around $* and $@ :

Both have the same behavior.

./bar.sh $* => bar.sh takes arg1 , arg2 and arg3 as separate arguments

./bar.sh $@ => bar.sh takes arg1 , arg2 and arg3 as separate arguments

Case 2: you use quotation marks around $* and $@ :

./bar.sh "$*" => bar.sh takes arg1 arg2 arg3 as one argument

./bar.sh " $@ " => bar.sh takes arg1 , arg2 and arg3 as separate arguments

More importantly, $* also ignores the quotation marks in the argument list. For example, if you put ./foo.sh arg1 "arg2 arg3" , even then:

./bar.sh "$*" => bar.sh will still get arg2 and arg3 as separate parameters!

./bar.sh " $@ " => will pass arg2 arg3 as the only parameter (which you usually want).

Please note that this difference only occurs if you put $* and $@ in quotation marks. Otherwise, they have the same behavior.

Official Documentation: http://www.gnu.org/software/bash/manual/bash.html#Special-Parameters

+3
source share

see here here :

 $# Stores the number of command-line arguments that were passed to the shell program. $? Stores the exit value of the last command that was executed. $0 Stores the first word of the entered command (the name of the shell program). $* Stores all the arguments that were entered on the command line ($1 $2 ...). " $@ " Stores all the arguments that were entered on the command line, individually quoted ("$1" "$2" ...). 

take an example

 ./command -yes -no /home/username so now.. $# = 3 $* = -yes -no /home/username $@ = ("-yes" "-no" "/home/username") $0 = ./command $1 = -yes $2 = -no $3 = /home/username 
+2
source share

They differ when cited:

 $ set "ab" cd $ echo $# 3 $ set "$*" $ echo $# 1 

 $ set "ab" cd $ echo $# 3 $ set " $@ " $ echo $# 3 

Here, only the second form stores the argument counter.

+1
source share

All Articles