zet

Zsh Fails Expectations Again: test and []

At this point I’m getting pretty fucking pissed off that as many people use and promote Zsh as they do. It’s fucking dangerous. If you regularly use and code in Zsh then you are likely a liability to any team you are on — especially in the cloud-native space where all scripting is pretty much POSIX and bash.

The last issue was the unexpected behavior with its moronic attempt to deal with floating point math. This time its the completely asinine handing of POSIX test and []. Why on Earth would you fuck with that?! Let me explain by just showing you the examples for yourself.

Here’s the code to try in each shell:

foo='some thing'
test $foo = 'some thing' && echo ok
[ $foo = 'some thing' ] && echo ok
[[ $foo = 'some thing' ]] && echo ok

With POSIX shell (dash) this is why you have to double quote everything including arguments to test which are the exact same thing as everything between single-bracket conditions [] (which can become a serious security issue:

/tmp/tmp.RO012GjBH3/some.sh: 4: test: some: unexpected operator
/tmp/tmp.RO012GjBH3/some.sh: 5: [: some: unexpected operator
/tmp/tmp.RO012GjBH3/some.sh: 6: [[: not found

In bash you are protected from the need to to quotes within the safe double-bracket conditions:

/tmp/tmp.RO012GjBH3/some.bash: line 4: test: too many arguments
/tmp/tmp.RO012GjBH3/some.bash: line 5: [: too many arguments
ok

But in fucking Zsh you don’t get what you would expect from either of the leading shells:

ok
ok
ok

Once again, Zsh fucks you over by trying to do the right thing. Is this safer? Yes. Is it what you expect? Hell no.

The point is that being consistent is far more important than being safer. In fact, being inconsistent will create situations where people create very unsafe code. Here’s what I mean.

People regularly say that Zsh is “POSIX compliant” and really have no idea what that even means. (None would know that not even Bourne shell was truly POSIX compliant, but that is another story.) These same people then proceed to code everything with /bin/sh (linked however to zsh) and create internal expectations and false assumptions about how POSIX works — particularly in the area of shell expansion injection security vulnerabilities. Then, when on a POSIX system, which is very likely the case if they are working with containers and cloud-native, they make those same assumptions and write absolutely crappy, insecure POSIX code.

Don’t believe me? Look through the absolute shit that is the 14,000 lines of tab completion code generated by Cobra, a popular Go commander. It is chuck full of these types of assumptions, probably because the primary developers of Cobra’s completion use Macs all day with Zsh and cannot write safe POSIX shell code if their lives depended on it.

Seriously, stop using Zsh for any type of scripting at all. Follow the principle of progressive enhancement in your learning and learn to code safe POSIX shell first. Then learn Bash. Finally, if you insist, learn the dumb-ass quirks of Zsh. As for me, Imma actively campaign against that shit-for-brains shell as much as I can.