-
Avoid syntax or semantics unique to bash, zsh, or any other specific shell, eg:
- array contructs
- parameter subtitution;
<()
or>()
{a,b,c}
or{1..10}
- the
function
keyword at the beginning of a function - C-like for loops,
for ((i=0; i<3; i++))
-
Avoid
basename
, useexpr
or parameter expansion (${variable##*/}) instead -
Avoid parsing
ls
output -
Use
=
over==
-
Use
case
overtest
or[
for regex -
Use
[
ortest
over[[
-
Use
command -v
ortype
overwhich
-
Use parameter expansion over
awk
,cut
orbasename
on simple strings -
Use
awk
oversed
,grep
,cut
,sort
,tr
orunique
-
Use
/bin/sh
over/bin/bash
or/usr/bin/env bash
-
Use
$(foo)
over\
foo`` -
Use
$((${i}+1))
over$(expr "${i}" + 1)
-
Use
:
as a sed separator, eg:sed -e 's:foo:bar:'
-
Use lowercase over uppercase, except in vars users will interact with, eg:
GLOBAL_VAR_PROGRAM
-
Use spaces over tabs
-
Avoid forking or using extra pipes when not necessary, eg,
Bad
is_directory() { [ -d "${1}" ] } sed 's:foo:bar:g' | sed 's:more:less:g' if is_directory "${directory}" printf "%s\\n" "${directory} is a directory" fi
Good
sed 's:foo:bar:g;s:more:less:g' if [ -d "${directory}" ] printf "%s\\n" "${directory} is a directory" fi [ -d "${directory}" ] && printf "%s\\n" "${directory} is a directory"
-
Use braces around multiple variables, eg,
Bad
var="$foo" var="$foo$bar" var="/path/$foo.suffix"
Good
var="${foo}" var="${foo}${bar}" var="/path/${foo}.suffix"
-
Use quotes when assigning values to variables, use single quotes when absolutely necesary
Bad
foo=bar bar=${foo}
Good
foo="bar" bar="${foo}"
-
Define functions with an underscore prefix, eg,
Bad
encode64() { steps }
Good
_encode64() { steps }
-
Prefer minimal style
Bad
if foo then bar fi if [ -z "${foo}" ]; then cmd fi if [ -z "${foo}" ]; then cmd else other_cmd fi _foo() { _foo__first_argument="${1}" printf "%s\\n" "${_foo__first_argument}" }
Good
if foo; then bar fi [ -z "${foo}" ] && cmd [ -z "${foo}" ] && cmd || other_cmd _foo() { printf "%s\\n" "${1}" }
-
Local variables should be named unique after their function name (or an abbreviation of it) and separated by doble underscore, avoid
local
Bad
_foo() { local basename="${1##*/}" } _foo_bar() { local basename="${1##*/}" }
Good
_foo() { _foo__basename="${1##*/}" } _foo_bar() { _fbar__basename="${1##*/}" }
-
Use
printf
overecho
(specially when echoing ${vars})Bad
echo "${foo}"
Good
printf "%s\\n" "${foo}"
-
Avoid fixed paths in commands:
Bad
[ -f /usr/bin/ps ] && /usr/bin/ps
Good
if command -v "ps" > /dev/null; then $(command -v "ps") fi
Better
[ -f "$(command -v "mplayer")" ] && $(command -v "mplayer")
-
Avoid -q in grep, git and other command, redirect stdout to /dev/null instead
Bad
grep -qs pattern file && return 0
Good
grep pattern file >/dev/null && return 0
-
Do NOT write to the file system, use vars or pipes instead
Bad
grep pattern file > /tmp/grep.output
Good
grep_output="$(grep pattern file)"
-
Use
||
and&&
over-a
and-o
Bad
if [ "-d" = "${1}" -o "--delete" = "${1}" ]; then foo fi
Good
if [ "-d" = "${1}" ] || [ "--delete" = "${1}" ]; then foo fi