Writing POSIX-Compatible Shell Scripts
Write portable shell scripts that work across bash, dash, ash, and other POSIX shells. Avoid bashisms and ensure cross-platform compatibility.
Detailed Explanation
POSIX Shell Compatibility
If your script uses #!/bin/sh, it must conform to the POSIX shell
specification. Many systems (Debian, Ubuntu) use dash as /bin/sh,
which does not support Bash-specific features.
Common Bashisms to Avoid
| Bashism | POSIX Alternative |
|---|---|
[[ condition ]] |
[ condition ] |
== in [ ] |
= |
${var//old/new} |
Use sed: `echo "$var" |
Arrays arr=(a b) |
Use positional params or multiple vars |
function name |
name() |
source file |
. file |
(( arithmetic )) |
$((arithmetic)) or expr |
<<< (here-string) |
`echo "string" |
select |
Manual menu loop |
read -p |
printf "prompt: "; read var |
Process sub <(cmd) |
Temp files or pipes |
Testing POSIX Compliance
Method 1: Test with dash
dash ./script.sh
Method 2: Use checkbashisms
checkbashisms ./script.sh
Method 3: Use shellcheck with --shell=sh
shellcheck --shell=sh ./script.sh
POSIX-Safe Patterns
String operations:
# Get filename extension (POSIX)
ext="${filename##*.}"
# Get directory name (POSIX)
dir="${filepath%/*}"
# Remove prefix (POSIX)
base="${var#prefix}"
Arithmetic:
# POSIX arithmetic
count=$((count + 1))
result=$((a * b + c))
# POSIX comparison
if [ "$count" -gt 10 ]; then
echo "More than 10"
fi
Local variables:
# local is not POSIX but widely supported
# For strict POSIX, use subshells for scoping:
my_func() (
var="local to function"
echo "$var"
)
# Parentheses instead of braces create a subshell
When to Use #!/bin/bash
Use bash when you need arrays, [[ ]], regex matching, process
substitution, or other Bash-specific features. Just be explicit with
#!/bin/bash or #!/usr/bin/env bash.
Use Case
System initialization scripts, package installation scripts, CI/CD pipelines that run on minimal Docker images (Alpine/busybox), and any script that must work across different Unix-like operating systems.
Try It — Shell Script Linter
Related Topics
SC2148: Missing Shebang Line in Shell Scripts
Script Setup
[ ] vs [[ ]] in Bash: Single vs Double Brackets
Deprecated Syntax
SC2006: Replace Backtick Command Substitution with $()
Deprecated Syntax
Bash Strict Mode: set -euo pipefail Explained
Script Setup
Shell Variable Default Values: Using ${var:-default} and ${var:=default}
Quoting