Writing Portable Scripts (Bash-isms vs POSIX sh)
In this page:
Choosing the Right Shebang
#!/usr/bin/env bash looks up bash on the current PATH rather than assuming it lives at /bin/bash, which makes a script more portable across systems (like some BSDs or containers) where bash is installed elsewhere.
Example: Choosing the Right Shebang
#!/usr/bin/env bash
echo "found bash via PATH lookup, running fine"
Login to try C/C++/Java/PHP code in the editor
Bash-Only Features to Watch For
Arrays, [[ ]] conditionals, local variables inside functions, and string substitution like ${var//pattern/repl} are all bash extensions that a strict POSIX sh does not support.
Warning: None of the features in this example (arrays, [[ ]], ${var//a/b}) are guaranteed to work under #!/bin/sh on every system.
Example: Bash-Only Features to Watch For
#!/bin/bash
fruits=("apple" "banana")
if [[ ${#fruits[@]} -eq 2 ]]; then
echo "arrays and [[ ]] are bash-specific features working here"
fi
text="hello-world"
echo "${text//-/ }"
Login to try C/C++/Java/PHP code in the editor
Writing the POSIX-Compatible Equivalent
When portability to plain sh matters, the same logic can usually be expressed with single-bracket [ ] tests, case statements, and plain variables instead of arrays, all of which are part of the POSIX standard.
Example: Writing the POSIX-Compatible Equivalent
#!/bin/bash
value="banana"
case $value in
apple) echo "it's an apple" ;;
banana) echo "it's a banana (POSIX-compatible case statement)" ;;
*) echo "unknown fruit" ;;
esac
if [ "$value" = "banana" ]; then
echo "single-bracket test also works everywhere"
fi
Login to try C/C++/Java/PHP code in the editor
- Using
#!/bin/shas the shebang while still relying on bash-only features like arrays or[[ ]], which fails on systems where/bin/shis a different, stricter shell. - Assuming
[[ ]], arrays,local, and+=are available everywhere; they are bash extensions, not part of POSIXsh. - Hardcoding
#!/bin/bashand assuming bash is always at that exact path;#!/usr/bin/env bashis more portable across systems where bash lives elsewhere.
#!/usr/bin/env bashfinds bash wherever it is on thePATH, which is more portable than hardcoding#!/bin/bash.- Arrays,
[[ ]],local, string manipulation like${var//a/b}, and namerefs are bash-isms not guaranteed in POSIXsh. - If a script must run under plain
sh, stick to[ ](single bracket), avoid arrays, and usecaseinstead of bash-only pattern matching. - Running
shellcheckwith the correct--shelltarget helps catch accidental bash-isms in a script meant to be POSIX-compliant.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first:
- Quoting Pitfalls and Why to Always Quote Variables
- set -euo pipefail as a Script Header
- Structuring a Script (Functions, main() Pattern, Exit at the End)
- Idempotent Scripts (Safe to Re-Run)
- Logging in Scripts (Timestamped log Function)
- Writing Portable Scripts (Bash-isms vs POSIX sh)
- Capstone: A Real-World Backup/Cleanup Script