-2

My understanding is that -n is the opposite of -z.

Testing -z...

#! /bin/bash

if [ -z $1 ]; then
  echo bar
fi
$ ./test1.sh
bar

$ ./test1.sh foo

Works as expected!

Testing -n...

#! /bin/bash

if [ -n $1 ]; then
  echo bar
fi
$ ./test1.sh
bar

$ ./test1.sh foo
bar

Does not work as expected unless I use quotes... Why?

Trying to figure out when to use quotes and when I can safely omit them.

Testing -n (with quotes)...

#! /bin/bash

if [ -n $1 ]; then
  echo bar
fi
$ ./test1.sh

$ ./test1.sh foo
bar

Works as expected!

sunknudsen
  • 6,356
  • 3
  • 39
  • 76
  • Use `[[ ... ]]` and no need to quote – anubhava May 03 '21 at 10:40
  • Thanks @anubhava, is it bad practice to use `[[]]` then? Trying to thoroughly understand when to use what. – sunknudsen May 03 '21 at 10:41
  • If you're using bash it is safer and better to use `[[ ... ]]`. `[` is archaic from bourne shell days and is actually an external executable. – anubhava May 03 '21 at 10:42
  • Now try `./test1.sh "foo bar"`. `Testing -n (with quotes).` there are no quotes. – KamilCuk May 03 '21 at 10:42
  • @KamilCuk `./test.sh: line 3: [: foo: binary operator expected` So I should either use double square brackets or always use double quotes? – sunknudsen May 03 '21 at 10:45
  • @anubhava Can you please expand on "external executable" in the context of variable that could contain sensitive data? – sunknudsen May 03 '21 at 10:58
  • `[` is usually `/bin/[` on most of the systems. In Unix to pass variables on command line safely to an external binary, one needs to quote it. Hence quoting is must to have when using `[` but not when using `[[ ...]]` which is builtin – anubhava May 03 '21 at 11:05
  • Thanks @anubhava... but is the content of variables leaked when using `[ `? Trying to figure out the security implications of using `[`? – sunknudsen May 03 '21 at 11:08

1 Answers1

1

Does not work as expected unless I use quotes... Why?

From man test (and see also posix test):

   -n STRING
          the length of STRING is nonzero

   STRING equivalent to -n STRING

   -z STRING
          the length of STRING is zero

When $1 is empty, then [ -n $1 ] executes [ -n ]. [ STRING ] is equivalent to [ -n STRING ], so [ -n ] is equivalent to [ -n -n ], and because -n is nonzero string, [ succeeds.

Check your scripts with http://shellcheck.net

Unquoted variable expansion undergo word splitting and filename expansion!

Research Difference between single and double quotes in Bash and When to wrap quotes around a shell variable? and https://mywiki.wooledge.org/Quotes


So I should ... always use double quotes?

As a rule of thumb you should always wrap expansions in double quotes.

So I should ... use double square brackets ... ?

The [[ is a bash extension not available in other shells, and from [[ documentation we know that: Word splitting and filename expansion are not performed on the words between the [[ and ]], so that's why there is no need to (but it does no harm) to double quote expansions between [[. [[ is specially handled by the shell, it's a special builtin with special syntax.

When working in bash-specific script that will never be ported, you may prefer [[ over [ because it should be tiny bit faster faster.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Thanks for helping out! According to some tests, `[[` appears to work in Z Shell as well... is that assumption correct? – sunknudsen May 03 '21 at 10:54
  • Do you mean `[` is executed in a sub shell? Can you please expand in the context of variable that contains sensitive information? This answer is amazing! – sunknudsen May 03 '21 at 10:59
  • According to https://stackoverflow.com/questions/2188199/how-to-use-double-or-single-brackets-parentheses-curly-braces, `test` and `[` are shell builtins. – sunknudsen May 03 '21 at 11:10
  • 1
    `Z Shell as well... is that assumption correct?` Well, you tested it, why ask me? I would trust my computer more then some random guy on the net. See zsh documentation, I do not use zsh. `Do you mean [ is executed in a sub shell?` `[` is not a "shell", it''s a command. `Can you please expand in the context of variable that contains sensitive information?` No, because I do not understand how would "sensitive information" change anything. `test and [ are shell builtins` Och, yes they are... I just remember that `[[` is tiny bit faster. – KamilCuk May 03 '21 at 11:13