Use when writing shell scripts that need to run across different systems, shells, or environments. Covers POSIX compatibility and platform differences.
View on GitHubFebruary 5, 2026
Select agents to install to:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/plugins/validation/shellcheck/skills/shell-portability/SKILL.md -a claude-code --skill shell-portabilityInstallation paths:
.claude/skills/shell-portability/# Shell Script Portability
Techniques for writing shell scripts that work across different platforms and environments.
## Shebang Selection
### Bash Scripts
```bash
#!/usr/bin/env bash
# Most portable for bash scripts
# Works on Linux, macOS, BSD
```
### POSIX Shell Scripts
```sh
#!/bin/sh
# For maximum portability
# Use only POSIX features
```
## Bash vs POSIX Differences
### Arrays (Bash only)
```bash
# Bash - arrays available
declare -a items=("one" "two" "three")
for item in "${items[@]}"; do
echo "$item"
done
# POSIX - use positional parameters or space-separated strings
set -- one two three
for item in "$@"; do
echo "$item"
done
```
### Test Syntax
```bash
# Bash - extended test
if [[ "$var" == "value" ]]; then
echo "match"
fi
# POSIX - basic test
if [ "$var" = "value" ]; then
echo "match"
fi
```
### String Operations
```bash
# Bash - regex matching
if [[ "$input" =~ ^[0-9]+$ ]]; then
echo "numeric"
fi
# POSIX - use case or external tools
case "$input" in
*[!0-9]*|'') echo "not numeric" ;;
*) echo "numeric" ;;
esac
```
### Arithmetic
```bash
# Bash - arithmetic expansion
(( count++ ))
if (( count > 10 )); then
echo "greater"
fi
# POSIX - expr or arithmetic expansion
count=$((count + 1))
if [ "$count" -gt 10 ]; then
echo "greater"
fi
```
## Platform Differences
### macOS vs Linux
```bash
# Date command differences
# GNU (Linux)
date -d "yesterday" +%Y-%m-%d
# BSD (macOS)
date -v-1d +%Y-%m-%d
# Portable approach
if date --version >/dev/null 2>&1; then
# GNU date
yesterday=$(date -d "yesterday" +%Y-%m-%d)
else
# BSD date
yesterday=$(date -v-1d +%Y-%m-%d)
fi
```
### sed Differences
```bash
# GNU sed - in-place edit
sed -i 's/old/new/g' file.txt
# BSD sed - requires backup extension
sed -i '' 's/old/new/g' file.txt
# Portable approach
sed 's/old/new/g' file.txt > file.txt.tmp && mv file.txt.tmp file.txt
# Or use a function
sed_inplace() {
if sed --version >/dev/null 2>&1; then