I have a script that fails to detect zero length strings,the script uses [ -n $value ]
in a bash conditional expression, i.e.
#!/usr/bin/env bash
value=""
if [ -n $value ]
then
echo "value is non-zero"
fi
result
value is non-zero
If I use [[ -n $value ]]
it works, i.e.
#!/usr/bin/env bash
value=""
if [[ -n $value ]]
then
echo "value is non-zero"
fi
using [[
produces no output as expected. From the man page:
[[ expression ]] Return a status of 0 or 1 depending on the evaluation of the conditional expression expression. Expressions are composed of the pri‐ maries described below under CONDITIONAL EXPRESSIONS. Word splitting and pathname expansion are not performed on the words between the [[ and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed. Conditional operators such as -f must be unquoted to be recognized as primaries.
I can't make out an explanation for the behaviour from this.
Why does [[
detect zero length strings but [
doesn't?
[[
is a compound command - is that because it performs multiple operations? e.g. does more work to make its use more user friendly? – the_velour_fog Nov 30 '15 at 04:52[[
is not more user-friendly, it is more innate.[
andtest
were, historically, separate executable commands found in$PATH
, and so shell[
builtins were designed to behave as an outside command would.[[
has never had that distinction, however, and so it has no need to behave as an outside executable might, and it can address names and information the shell possesses as if it is its own (because it is). – mikeserv Nov 30 '15 at 04:55[
andtest
ARE external commands, but many shells also have them as built-ins for convenience and speed - but the built-in versions are bug-for-bug compatible so they don't break existing scripts. – cas Nov 30 '15 at 05:05[
is abash
builtin as well, but it is a more separate routine than is[[
. – mikeserv Nov 30 '15 at 05:05[
andtest
are external commands if you have installed them. historically, they always were, and had nothing to do with the shell at all. – mikeserv Nov 30 '15 at 05:07/usr/bin/[
and/usr/bin/test
are in GNU coreutils. – cas Nov 30 '15 at 05:09[
is installed and used by bash - whenever you use[
you need to have the mindset of I'm calling another program so I need to handle parameter passing accordingly – the_velour_fog Nov 30 '15 at 05:12ksh93
) includes neither. – mikeserv Nov 30 '15 at 05:13test
,[
and their implementations, their history is that of separate programs so you need to treat them as such when you pass parameters to them. – the_velour_fog Nov 30 '15 at 05:28