How can I test for POSIX compliance of shell scripts?

Unfortunately, 'portable' is usually a stronger requirement than 'POSIX-compliant' for shell scripts. That is, writing something that runs on any POSIX shell isn't too hard, but getting it to run on any real-world shell is harder.

You can start by installing every shell in your package manager, in particular debian's posh sounds like what you want (Policy-compliant Ordinary SHell). Debian's policy is POSIX with a few exceptions (echo -n specified, local...).

Beyond that though, testing has to cover a few shells (/bin/sh especially) on a range of platforms. I test on Solaris (/bin/sh and xpg4/sh), and BSD. AIX and HP-UX are very compliant and don't cause problems. bash is a little world of its own.

I'd recommend the Autoconf guide to portable shell, which is absolutely brilliant and saves a lot of time. Large chunks of it are obsolete, but that's OK; just skip TruUnix and Ultrix and so on if you don't care!


You can use ShellCheck (GitHub) as a linter for your shell scripts. There is also an online version.

To detect POSIX compatibility issues (e.g. SC2039), the shebang line of your shell script should be #!/bin/sh. You can also pass --shell=sh to shellcheck.

Example (test.sh):

#!/bin/sh
if [[ $HOSTNAME == test ]]; then
    echo fail &> foo
fi

Result (shellcheck test.sh):

In test.sh line 2:
if [[ $HOSTNAME == test ]]; then
   ^-- SC2039: In POSIX sh, [[ ]] is undefined.
      ^-- SC2039: In POSIX sh, HOSTNAME is undefined.    

In test.sh line 3:
    echo fail &> foo
              ^-- SC2039: In POSIX sh, &> is undefined.

Bash will run in POSIX-compliant mode if the POSIXLY_CORRECT environment variable is set. From the manpage:

   POSIXLY_CORRECT
          If  this  variable  is  in the environment when bash starts, the
          shell enters posix mode before reading the startup files, as  if
          the  --posix  invocation option had been supplied.  If it is set
          while the shell is running, bash enables posix mode, as  if  the
          command set -o posix had been executed.

Many other GNU utilities will also honor POSIXLY_CORRECT, so if you're on a system with predominantly GNU tools (e.g. most Linux systems), this is a good start if your goal is POSIX conformance.