Portable Shell constructs

Utilities used in a shell script.

The Gnu coding standard - Utilities in Makefiles list them:

The configure script and the Makefile rules for building and installation should not use any utilities directly except these: awk cat cmp cp diff echo egrep expr false grep install-info ln ls mkdir mv printf pwd rm rmdir sed sleep sort tar test touch tr true

Converting bash syntax to dash

This table is extracted from Bashism look at the original for more info.

construct bash dash
functions function f { echo hello world; } f() { echo hello world; }
cases ;;& ;& etc None. Duplicate the case (use a function to avoid code duplication)
C-like for loop for ((i=0; i<3; i++)); do echo "$i" done i=0 ; while [ "$i" -lt 3 ]; do echo "$i" ; i=$(($i+1)) done
expand sequences echo $'hello\tworld' printf "hello\tworld\n"
extended glob +( ) @( ) !( ) *( ) sometimes you can use several globs, sometimes you can use find(1)
select select implement the menu yourself, use a command like dialog
Brace Expansion {a,b,c} or {1..10}  
process substitutions foo <(bar) mkfifo fifo; bar > fifo & foo < fifo
  ${name:n:l} $(expr "x$name" : "x.\{,$n\}\(.\{,$l\}\)")
  ${name/foo/bar} $(printf '%s\n' "$name" | sed 's/foo/bar/')
  ${!name} use eval (dangerous)
arrays   positional parameters, use IFS and set -f, eval (dangerous)
simple test [[ use [ and use double quotes around the expansions [ "$var" = "" ]
pattern matching [[ foo = *glov ]] use case or expr or grep
equality with test == use = instead
compare lexicographically. <> no change
modification times [[ file1 -nt file2 ]] or -ot [ "$(find 'file1' -prune -newer 'file2')" ] or [ "file1" -nt "file2" ]
files are the same hardlink [[ file1 -ef file2 ]] [ "file1" -ef "file2" ]
(( )) var=((3+1)) var=$((3+1))
(( )) ((3 + 1 < 5)) [ $((3 + 1)) -lt 5 ] or [ "$((3 + 1 < 5))" -ne 0 ]
pre/post increment/decrement ++ -- i=$((i+1)) or : $((i+=1))
comma operator , (ok in ash) : "$((...))"; cmd "$((...))"
exponentiation ** (ok in ash)
let let x=15; let x-- x=15; x=$((x - 1))
redirect both stdout and stderr >& and &> command > file 2>&1 or command 2>&1 | command2
duplicate and close m>&n- m<&n- m>&n n>&-
herestring <<<"string" echo "string"| command
source source lib/xxx.sh . lib/xxx.sh
expand ~ in PATH PATH="~/bin:$PATH" `` PATH=”$HOME/bin:$PATH”``