Saturday, 23 July 2016

"$@" is a shell idiom

TL;DR: Use "$@" when you want to pass arguments unchanged to a function or program.

When you read the shell documentation you will see that there are two main ways to refer to all the arguments for passing to a function or program: $* and "$@". What is the difference? This test script will demonstrate it:

#!/bin/sh

testargs() {
       echo testargs: $# arguments
       showargs $*
       showargs "$@"
}

showargs() {
       echo showargs: $# arguments
       for i
       do
               echo $i
       done
}

testargs 1 2 3
testargs word 'quoted phrase' word

The result should be:
testargs: 3 arguments
showargs: 3 arguments
1
2
3
showargs: 3 arguments
1
2
3
testargs: 3 arguments
showargs: 4 arguments
word
quoted
phrase
word
showargs: 3 arguments
word
quoted phrase
word
As you can see, the difference is manifest when an argument has whitespace. "$@" preserves the arguments, not parsing it again to break up at whitespace in arguments. Think if it as an idiom meaning pass arguments verbatim.

Why would you ever use $* though? Here's a place where you shouldn't use "$@".
su -c "$*" user
If you were to use "$@" and it contained multiple arguments, only the first argument would be used by -c and the others would follow, causing a syntax error. This however means that if you want to pass arguments with whitespace to -c, you have to quote them and escape the quotes too.

No comments:

Post a Comment