Running
shellcheck <file>...
Check one or more scripts
shellcheck -
Read the script from stdin
shellcheck -x <file>
Also follow files it sources
shellcheck -a <file>
Report issues in sourced files too
shellcheck --files-from <list>
Read file names from a list
find . -name '*.sh' -exec shellcheck {} +
Check every script in a tree
shellcheck --version
Show the installed version
apt install shellcheck
Install on Debian/Ubuntu
brew install shellcheck
Install on macOS
docker run --rm -v "$PWD:/mnt"
koalaman/shellcheck:stable <file>
Run without installing
Dialect and checks
-s <shell>
Force sh, bash, dash, ksh or busybox
-S <severity>
Minimum level: error, warning, info, style
-e <codes>
Exclude codes, comma separated
-i <codes>
Report only these codes
-o <names>
Enable optional checks
-o all
Enable every optional check
--list-optional
List the optional checks
-P <dirs>
Search path for sourced files
--extended-analysis=false
Turn dataflow analysis off (faster)
-C / --color[=<when>]
Colour output: always, never, auto
-W <n>
Number of wiki links shown (0 hides)
Output and exit codes
-f tty
Readable text with code excerpts (default)
-f gcc
file:line:col lines for editors
-f json1
Machine-readable JSON with a comments array
-f checkstyle
Checkstyle XML for CI dashboards
-f diff
Unified diff of automatic fixes
-f quiet
No output, stop at the first finding
echo $?
Exit code: 0 clean, 1 findings
SHELLCHECK_OPTS="--shell=bash -e SC2016"
Default flags for every run
Directives
# shellcheck disable=SC2086
Ignore a code for the next command
# shellcheck disable=SC2034,SC2154
Ignore several codes
# shellcheck disable=SC2000-SC2999
Ignore a range of codes
# shellcheck disable=all
Ignore every code
# shellcheck source=<path>
Tell it which file a source loads
# shellcheck source=/dev/null
Do not follow this source
# shellcheck source-path=SCRIPTDIR
Look up sources next to the script
# shellcheck shell=bash
Set the dialect for this file
# shellcheck enable=<name>
Switch on an optional check (file-wide)
Common warnings
SC2086
Quote $var to stop splitting and globbing
SC2046
Quote $(...) to stop word splitting
SC2068
Use "$@" instead of unquoted $@
SC2034
Variable assigned but never used
SC2154
Variable used but never assigned
SC2164
Use cd ... || exit in case cd fails
SC2155
Declare and assign separately
SC2162
read without -r mangles backslashes
SC2006
Use $(...) instead of backticks
SC2016
Single quotes do not expand variables
SC2012
Do not parse ls; use a glob or find
SC2002
Useless cat; redirect with < file
SC2015
A && B || C is not if-then-else
SC2181
Test the command directly, not $?
SC2207
Use mapfile or read -a, not arr=($(cmd))
SC2115
Guard rm -rf "$dir/" against empty dir
SC2148
Add a shebang or a shell directive
SC1090 / SC1091
Cannot follow source; use -x or a source= directive
SC3010
[[ is not POSIX; use [ in sh scripts
SC2064
Quote trap commands with single quotes