Consider the following in bash:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="acdec3c3d8ecc8c9cec5cdc281c0cddc">[email protected]</a>:/tmp I=$(echo) <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0d7f6262794d69686f646c6320616c7d">[email protected]</a>:/tmp echo "$I" <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bac8d5d5cefadedfd8d3dbd497d6dbca">[email protected]</a>:/tmp [ -z "$I" ] && echo "TRUE" || echo "FALSE" TRUE
This means that variable $I is zero. The same I could achieve with negation test to see if variable is non zero, and ! makes test reverse so it checks is variable zero
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4b3924243f0b2f2e29222a2566272a3b">[email protected]</a>:/tmp ! [ -n "$I" ] && echo "TRUE" || echo "FALSE" TRUE <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d6a4b9b9a296b2b3b4bfb7b8fbbab7a6">[email protected]</a>:/tmp
So, my question is, are there any special cases when to use -z and ! -n , or vice versa ! -z and -n as they are basically doing the same test?
Thanks
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
1. [ -z "$var" ]
2. [ ! -n "$var" ]
3. ! [ -n "$var" ]
4. [ ! "$var" ]
5. [ "$var" = '' ]
6. [ ! "$var" != '' ]
7. [ '' = "$var" ]…²
Are all functionally equivalent in POSIX shells¹. The Bourne shell¹ didn’t have the ! keyword, so wouldn’t support 3 above and had all sorts of bugs with special values of $var (like =, -n, !…) in all but 7 (many other shells also had similar bugs).
In a similar vein, you can (and should) use [ "$a" = "$b" ] && [ "$x" = "$y" ] in place of [ "$a" = "$b" -a "$x" = "$y" ], the latter being deprecated and non-reliable.
The ! of 3 is a POSIX shell feature. It still makes sense of the test/[ utility to support its own ! operator (as in 2/6) for other shells or non-shell applications that may want to use it and negate conditions.
The test utility was introduced by Unix v7. Before that, there was a if utility that had !, =, !=, -a/-o, but no -n/-z.
I suppose -n/-z were added for convenience (test -n "$var" being a short form for test "$var" != '' and -z being added for consistency)
¹ Technically, while test/[ is built in virtually all Bourne-like shells, that’s not mandated by POSIX and early versions of the Bourne shell didn’t have it built-in. While the Almquist shell always had a test builtin, some BSDs did not enable it so some BSDs did not have a [/test built in sh until the 2000s. In any case, regardless of whether a particular shell has a [/test command built-in, all POSIX systems will also have a [/test command on the file system (which may or may not behave the same as the [/test builtin command of any shell on the system).
² That’s not to say that’s the only commands that can be used to test if a variable is the empty string.
case $var in "") ... esac
is one way that doesn’t involve running any command.
expr "x$var" : 'x$' > /dev/null
${var:+"false"}
awk 'BEGIN{exit(ARGV[1] != "")}' "$var"
[ "${#var}" -eq 0 ]
Are more examples of convoluted ways to do that.
Some Korn-like shells like bash also have some built-in conditional and arithmetic constructs that aim at replacing the [ command ([[ -z $var ]], ((${#var} == 0))…).
Method 2
You are given -n and -z for the same reason that other test suites give you both == and !=, or AND and NOT. Some test cases can be made a lot clearer to future maintainers by eschewing double-negatives. Also, as mentioned in an above comment, ancient incarnations of sh (i. e. the Bourne and Thompson shells), as opposed to modern POSIX sh did not have a ! keyword to negate the truthiness of test expressions.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0