function wtf() {
echo "\$*='$*'"
echo "\$@='$@'"
echo "\$@='"$@"'"
echo "\$@='""$@""'"
if [ -n "$*" ]; then echo " [ -n \$* ]"; else echo "![ -n \$* ]"; fi
if [ -z "$*" ]; then echo " [ -z \$* ]"; else echo "![ -z \$* ]"; fi
if [ -n "$@" ]; then echo " [ -n \$@ ]"; else echo "![ -n \$@ ]"; fi
if [ -z "$@" ]; then echo " [ -z \$@ ]"; else echo "![ -z \$@ ]"; fi
}
wtf
produces
$*='' $@='' $@='' $@='' ![ -n $* ] [ -z $* ] [ -n $@ ] [ -z $@ ]
though it seems to me that [-n $@]
should be false because 7.3 Other Comparison Operators indicates that [ -n "$X" ]
should be the inverse of [ -z "$X" ]
for all $X
.
-z
string is null, that is, has zero length
String='' # Zero-length ("null") string variable. if [ -z "$String" ] then echo "\$String is null." else echo "\$String is NOT null." fi # $String is null.
-n
string is not null.
The
-n
test requires that the string be quoted within the test brackets. Using an unquoted string with! -z
, or even just the unquoted string alone within test brackets (see Example 7-6) normally works, however, this is an unsafe practice. Always quote a tested string. [1]
I know $@
is special but I did not know it was special enough to violate boolean negation. What is happening here?
$ bash -version | head -1
GNU bash, version 4.2.42(2)-release (i386-apple-darwin12.2.0)
The actual numeric exit codes are all 1
or 0
as per
$ [ -n "$@" ]; echo "$?"
0
bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc.
Again, $() is a command substitution which means that it “reassigns the output of a command or even multiple commands; it literally plugs the command output into another context” (Source).
The echo command is used to display a line of text that is passed in as an argument. This is a bash command that is mostly used in shell scripts to output status to the screen or to a file.
$# is the number of positional parameters passed to the script, shell, or shell function. This is because, while a shell function is running, the positional parameters are temporarily replaced with the arguments to the function. This lets functions accept and use their own positional parameters.
When $@
is empty, "$@"
doesn't expand to an empty string; it is removed altogether. So your test is not
[ -n "" ]
but rather
[ -n ]
Now -n
isn't an operator, but just a non-empty string, which always tests as true.
"$@"
doesn't do what you expect. It's not a different form of "$*"
, it expands to the quoted list of arguments passed to the current script.
If there are no arguments, it expands to nothing. If there are two arguments a
and b c
, then it expands to "a" "b c"
(i.e. it preserves whitespace in arguments) while "$*"
expands to "a b c"
and $*
would expand to a b c
(three words).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With