Personal guidelines for sh scripting

Bad

var="$foo"
var="$foo$bar"
var="/path/$foo.suffix"

Good

var="${foo}"
var="${foo}${bar}"
var="/path/${foo}.suffix"

Bad

encode64()
{
    steps
}

Good

_encode64()
{
  steps
}

Bad

if foo
then
    bar
fi
 
if [ -z "${foo}" ]; then
    cmd
fi
 
if [ -z "${foo}" ]; then
    cmd
else
    other_cmd
fi
 
_function()
{
    steps
}

Good

if foo; then
    bar
fi
 
[ -z "${foo}" ] && cmd
 
[ -z "${foo}" ] && cmd || other_cmd
 
_function() {
    steps
}

Bad

_foo()
{
    local first_argument="${1}"
}

Good

_foo()
{
    _foo__first_argument="${1}"
}

Bad

foo=bar
bar=${foo}

Good

foo="bar"
bar="${foo}"

Bad

echo "${foo}"

Good

printf "%s\\n" "${foo}"

Bad

[ -f /usr/bin/ps ] && /usr/bin/ps

Good

if command -v "ps" > /dev/null; then
    $(command -v "ps")
fi

Better

[ -f "$(command -v "ps")" ] && $(command -v "ps")

Bad

ls | grep -qs file && return 0

Good

ls | grep file >/dev/null && return 0

Bad

ls > /tmp/ls.output
cat /tmp/ls.output && rm /tmp/ls.output

Good

ls_output="$(ls)"
printf "%s\\n" "${ls_output}"

Better

printf "%s\\n" "$(ls)"

Bad

[ "${cmd}" = "foo" ] && cmd

Good

[ X"${cmd}" = X"foo" ] && cmd

Bad

if [ "-d" = "${1}" -o "--delete" = "${1}" ]; then
    foo
fi

Good

if [ X"-d" = X"${1}" ] || [ X"--delete" = "${1}" ]; then
    foo
fi
1)
i=0; i<3; i++
2)
${i}+1