I say this as somebody who has written shell scripts for almost 20 years.
Constructs like
if [ "X${str1}" = "X${str2}" ]
to avoid things exploding because a zero length variable might exist is a stupid and ugly hack.Not to mention the hell that is trying to use a user supplied filename safely in shellscript. (for the uninitiated, a unix filename can contain any character, and any sequence of bytes besides / and 0x00, including newlines, backspaces, shell meta-charachters and so many more exciting things)
That has less to do with POSIX compliance, as opposed to working around quirks with less-compliant historical implementations. Also, I think you'd have to dig pretty deep to find a test that doesn't support zero-length arguments; you'd be safe as long as you quote your variables.
The actual problem of ambiguity arises from variables that are also syntax, like '(', or '!', when using compound expressions (which you should avoid anyway).
# this is bad (also obsolete)
[ "$var" != foo -a "$var" != bar ]
# this is good (and fully POSIX compliant)
[ "$var" != foo ] && [ "$var" != bar ]
# you probably don't need to care for systems where this was necessary
[ "X$var" != Xfoo ] && [ "X$var" != Xbar ]I ran shellcheck to see if it was bash or sh and it didnt make a peep:). My Q is just asking if there is another similar quality tool. I see how you could interperit it the other way, thanks for asking.
bash is not POSIX-compliant. This script is.
Similarly, not every Linux distribution puts bash in the same place, e.g. NixOS. So blindly putting `#!/bin/bash` as your shebang will result in a broken script on those systems.
You can just install bash or move it around to suit your script, but maybe you're shipping this script for other people to use and can't control their environments. It's easier to make a handful of changes to the script instead. This is why some people care about portability.
But the modern reason is https://en.wikipedia.org/wiki/Almquist_shell (ash) and its descendant, dash. Busybox environments ship with ash as the only available shell, unless you manually build another shell into the busybox chroot. As well, many initrd/initramfs environments have only one shell, usually dash. When scripting either of these, you have to write pure POSIX scripts.
And—mostly due to inertia—this tends to apply to all such environments, no matter their size. My Synology NAS (because it’s technically a busybox env) doesn’t have bash, despite having huge honking disks! Neither does CoreOS (because it’s technically a PXE initramfs env), despite not being intended as a “link-bandwidth-constrained” PXE environment at all. They’re just descended from these “lineages” of OSes that were used on more constrained devices in more constrained times, so their maintainers have kept to the old embedded-system ways.
On top of this, as the ash wiki article says, Debian made a choice to make dash their /bin/sh, and then forced all system scripts to use it, thus forcing them to be rewritten to be POSIX-compatible. (I think this was done with goal of lower memory-usage for constrained Debian environments that might still need to install some arbitrary subset of Debian system services.)
There was also another kind of pressure, 10-20 years ago, with Linux single-floppy or low-link-bandwidth PXE boot environments wanting to be as slim as possible, and therefore not shipping with bash.
https://www.gnu.org/software/bash/manual/html_node/Bash-POSI...
An x86-64 CPU boots in 16-bit real mode. An explicit option has to be used to switch it to 64-bit long mode.
That doesn’t mean that it’s not a 64-bit CPU.
$ echo I am posix compliant &>/dev/null