News for hackers. Stuff that matters.
Re:Elegant Bash Conditionals by stonesweep on Tuesday March 02, 2021 @02:45PM (#26319583)
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 search "[["

[3] https://www.zsh.org/mla/users/2011/msg00161.html

There are no comments on this comment yet.