4 ms·
The [ character is actually the program called "test"[1], so you can think of it as just running grep or sed or any other external binary/program, whereas the [
by stonesweep 6y ago
The [ character is actually the program called "test"[1], so you can think of it as just running grep or sed or any other external binary/program, whereas the [[ replacement is shell-specific builtin; this blog is not using "bash-ism" but instead the external test operator from `coreutils` which generally would work from sh, zsh and whatever but on zsh, it doesn't work the same (kinda, it's more that the comparison EQUALS operator doesn't work well with [ but it's fine with [[).
Here it is in pdksh:
# [ "Z" == "z" ] && echo Bob
# [ "Z" == "Z" ] && echo Bob
Bob
I chose pdksh on purpose - because _it_ also supports [[ (builtin like bash)[2], so while [[ is a "bash-ism" it's actually present in some/many other shells as well. However, the operational aspect is not identical between [ and [[, both in the bash and pdksh implementations and let's add zsh to show the same line of shell break:
# [[ "Z" == "Z" && "A" == "A" ]] && echo Bob
Bob
# [ "Z" == "Z" && "A" == "A" ] && echo Bob
pdksh: [: missing ]
# [[ "Z" == "Z" && "A" == "A" ]] && echo Bob
Bob
# [ "Z" == "Z" && "A" == "A" ] && echo Bob
-bash: [: missing `]'
# [[ "Z" == "Z" && "A" == "A" ]] && echo Bob
Bob
# [ "Z" == "Z" && "A" == "A" ] && echo Bob
zsh: = not found
The [ operator requires that you use the bash/pdksh method to combine them with && "outside the brackets" in a more POSIX like use, like so:
# if ([ "Z" == "Z" ] && [ "A" == "A" ]); then echo Bob; fi;
Bob
...except on zsh, because (surprise!) zsh has decided to internalize the [ command rather than use the external one (which works OK); but it also has a problem with the "=" sign being used like this[3] with the test operator. zsh requires we then handle the == sign by quoting it (or unsetting a value internally):
# if [ "Z" == "Z" ] && [ "A" == "A" ]; then echo Bob; fi;
zsh: = not found
# if [ "Z" '==' "Z" ] && [ "A" '==' "A" ]; then echo Bob; fi;
Bob
This last example is a subtle point - the use of [[ is actually _more_ compatible between bash/pdksh/zsh than the use of [ due to the way zsh handles the input which is different than bash/pdksh and even old school POSIX Bourne shell (/bin/sh).
This got kinda long sorry, hope it helps.
[1] there's actually a binary "[" and a binary "test" in the `coreutils` package on most systems, however I'm not sure why they have different binary file sizes to be honest
[2] https://linux.die.net/man/1/pdksh https://linux.die.net/man/1/pdksh search "[["
[3] https://www.zsh.org/mla/users/2011/msg00161.html https://www.zsh.org/mla/users/2011/msg00161.html