Learn Docker With My Newest Course

Dive into Docker takes you from "What is Docker?" to confidently applying Docker to your own projects. It's packed with best practices and examples. Start Learning Docker →

Test If Your Shell Scripts Are POSIX Compliant with ShellCheck

blog/cards/test-if-your-shell-scripts-are-posix-compliant-with-shellcheck.jpg

Even if you're using a Bash shebang you can run ShellCheck with the --shell flag to supply a different shell to check against.

Quick Jump: Demo Video

I’ve done a video in the past about ShellCheck. It’s an excellent tool to perform static analysis against various flavors of shell scripts.

Often times I’ll try to create shell scripts that are POSIX compliant. This usually means setting #!/usr/bin/env sh as the Shebang and trying not to use Bash specific features unless it makes sense. I’m very pragmatic about this tho, if something is much more readable or easier to do with Bash I’ll use it without fretting over it.

Demo Video

Timestamped Table of Contents

  • 0:08 – Two conditions, one is POSIX compliant and the other is not
  • 0:38 – We can use the –shell sh flag with ShellCheck
  • 1:10 – It’s useful to ensure compatibility when you want it
  • 2:18 – The shorthand flag is -s sh

Code example

Follow along with touch demo && chmod +x demo and then add this to the file:

#!/usr/bin/env bash

NAME="nick"

if [ "${NAME}" = "nick" ] || [ "${NAME}" = "nicholas" ]; then
    echo "Shell compatible: Hey Nick!"
fi

if [[ "${NAME}" = "nick" || "${NAME}" = "nicholas" ]]; then
    echo " Bash compatible: Hey Nick!"
fi

Verify that the script is functional:

$ ./demo
Shell compatible: Hey Nick!
 Bash compatible: Hey Nick!

Confirm it’s compatible with bash but not sh:

# This will return no warnings since it's all good with Bash:
shellcheck demo

# Run ShellCheck with a custom shell to check against:
shellcheck --shell sh demo

The second command will throw this warning since it’s not POSIX compliant shell scripting:

In demo line 9:
if [[ "${NAME}" = "nick" || "${NAME}" = "nicholas" ]]; then
   ^-- SC2039: In POSIX sh, [[ ]] is undefined.

For more information:
  https://www.shellcheck.net/wiki/SC2039 -- In POSIX sh, [[ ]] is undefined.

That’s because [[ ]] was introduced specifically with Bash. There’s a bunch of other things that are Bash specific too which is why having ShellCheck around is great because you don’t need to keep all of the rules in your head.

For this specific example I’d prefer using the POSIX compliant shell version. In my opinion while the Bash version it is more concise it is less readable at a glance.

On the other hand double brackets offer convenient ways to do regular expression and string comparisons which I will use as needed. That’s something we can cover in a future post.

How far down the POSIX compliance rabbit hole do you go? Let me know below.

Never Miss a Tip, Trick or Tutorial

Like you, I'm super protective of my inbox, so don't worry about getting spammed. You can expect a few emails per month (at most), and you can 1-click unsubscribe at any time. See what else you'll get too.



Comments