POSIX-Compatible Shell Scripting
Intermediatev1.0.0
Write portable shell scripts that work across Linux, macOS, and BSD — POSIX sh compatibility, avoiding Bash-specific features, and handling platform differences.
Content
Overview
POSIX sh is the portable shell standard that works on any Unix-like system. When you need scripts to run on Linux, macOS, BSD, Docker alpine, and embedded systems, POSIX compliance ensures portability.
Why This Matters
- -Portability — runs on any Unix system, not just Linux
- -Docker — alpine images use ash/busybox, not bash
- -CI/CD — some runners have minimal shell environments
- -macOS — default shell is zsh, and bash is outdated (3.2)
Bash vs POSIX Differences
| Feature | Bash | POSIX sh |
|---|---|---|
| Test syntax | `[[ $x == y ]]` | `[ "$x" = "y" ]` |
| Arrays | `arr=(a b c)` | Not available |
| Process substitution | `<(command)` | Not available |
| Here strings | `<<< "string"` | Not available |
| String replacement | `${var//old/new}` | Use `sed` or `tr` |
| Regex matching | `[[ $x =~ regex ]]` | Use `grep` or `expr` |
| Arithmetic | `(( x++ ))` | `x=$((x + 1))` |
| Local variables | `local var` | `local var` (supported in practice) |
POSIX-Compatible Patterns
Platform-Specific Workarounds
Best Practices
- -Use
#!/bin/shfor portable scripts,#!/usr/bin/env bashfor Bash-specific - -Test on both Linux and macOS before declaring portability
- -Use
printfinstead ofecho(echo behavior varies across platforms) - -Avoid arrays — use positional parameters or newline-separated strings
- -Use
command -vto check for available commands - -For complex portability needs, consider Python or Go instead
Common Mistakes
- -Using #!/bin/sh with Bash-specific features (works on Linux, breaks on alpine)
- -Assuming GNU coreutils on macOS (macOS uses BSD versions)
- -Using echo with flags (
echo -e) — not portable - -Relying on /bin/bash existing (not present in alpine Docker images)
FAQ
Discussion
Loading comments...