SHELLCHECK(1)
SHELLCHECK(1) π β¨
okay bestie you clicked on the manpage for shellcheck and I'm about to make it make sense. this is part 1 so don't go anywhere, there's more coming π«Ά
πΈ NAME πΈ
shellcheck β Shell script analysis tool π
π¦ SYNOPSIS π¦
shellcheck [OPTIONS...] FILES...
like, you give it some files, and optionally some options. that's the whole shape of it, periodt.
π DESCRIPTION π
ShellCheck is a static analysis and linting tool for sh/bash scripts. no cap. it's mostly built to catch the classic beginner-to-intermediate level syntax oopsies and pitfalls β the ones where your shell just gives you some cryptic lil error or does something genuinely unhinged instead of telling you what's wrong π β but it also reports on a handful of more advanced issues where the corner cases can cause delayed failures. those are the sneaky ones and honestly they're so annoying.
The way ShellCheck works is that it gives shell specific advice. so look at this line:
(( area = 3.14*r*r ))
and now watch how the answer changes based on who's running it, it's giving "it depends" and it's right:
- For scripts starting with
#!/bin/sh(or when using-s sh), ShellCheck will warn that(( .. ))is not POSIX compliant (similar tocheckbashisms). - For scripts starting with
#!/bin/bash(or using-s bash), ShellCheck will warn that decimals are not supported. - For scripts starting with
#!/bin/ksh(or using-s ksh), ShellCheck will not warn at all, as ksh supports decimals in arithmetic contexts.
see?? same line, three totally different verdicts. context is everything bestie β¨
β¨ OPTIONS β¨
okay here's the whole menu, every single one, no skips because we don't do that here π
-a,--check-sourcedβ Emit warnings in sourced files. Normallyshellcheckwill only warn about issues in the specified files. With this option, any issues in sourced files will also be reported. so the drama doesn't stop at the front door anymore πͺ-C[WHEN],--color[=WHEN]β For TTY output, enable colors always, never or auto. The default is auto.--colorwithout an argument is equivalent to--color=always.-i CODE1[,CODE2...],--include=CODE1[,CODE2...]β Explicitly include only the specified codes in the report. Subsequent-ioptions are cumulative, but all the codes can be specified at once, comma-separated as a single argument. Include options override any provided exclude options. so-iwins the argument, iconic behavior honestly π-e CODE1[,CODE2...],--exclude=CODE1[,CODE2...]β Explicitly exclude the specified codes from the report. Subsequent-eoptions are cumulative, but all the codes can be specified at once, comma-separated as a single argument.--extended-analysis=true/falseβ Enable/disable Dataflow Analysis to identify more issues (default true). If ShellCheck uses too much CPU/RAM when checking scripts with several thousand lines of code, extended analysis can be disabled with this flag or a directive. This flag overrides directives and rc files. so it's the boss of the other settings, respect it.-f FORMAT,--format=FORMATβ Specify the output format ofshellcheck, which prints its results in the standard output. Subsequent-foptions are ignored β first one wins β seeFORMATSbelow for more information.--list-optionalβ Output a list of known optional checks. These can be enabled with-oflags orenabledirectives. window shopping ποΈ--norcβ Don't try to look for.shellcheckrcconfiguration files. going no-contact with your rc files, valid.--rcfile RCFILEβ Prefer the specified configuration file over searching for one in the default locations. picking your favorite child, we love to see it.-o NAME1[,NAME2...],--enable=NAME1[,NAME2...]β Enable optional checks. The special nameallenables all of them. Subsequent-ooptions accumulate. This is equivalent to specifyingenabledirectives.-P SOURCEPATH,--source-path=SOURCEPATHβ Specify paths to search for sourced files, separated by:on Unix and;on Windows. This is equivalent to specifyingsearch-pathdirectives.-s shell,--shell=shellβ Specify Bourne shell dialect. Valid values aresh,bash,dash,ksh, andbusybox. The default is to deduce the shell from the file's shell directive, shebang, or.bash/.bats/.dash/.kshextension, in that order.shrefers to POSIXsh(not the system's), and will warn of portability issues.-S SEVERITY,--severity=severityβ Specify minimum severity of errors to consider. Valid values in order of severity areerror,warning,infoandstyle. The default isstyle.-V,--versionβ Print version information and exit. short and sweet, love a diva who knows when to leave π-W NUM,--wiki-link-count=NUMβ For TTY output, showNUMwiki links to more information about mentioned warnings. Set to0to disable them entirely.-x,--external-sourcesβ Followsourcestatements even when the file is not specified as input. By default,shellcheckwill only follow files specified on the command line (plus/dev/null). This option allows following any file the script may source.
This option may also be enabled using external-sources=true in .shellcheckrc. This flag takes precedence.
FILES...β One or more script files to check, or"-"for standard input. yeah you can pipe it in, she's flexible like that π
π FORMATS π
pick your flavor bestie, there's a -f for every vibe
tty
Plain text, human readable output. This is the default.
gcc
GCC compatible output. Useful for editors that support compiling and showing syntax errors.
For example, in Vim, :set makeprg=shellcheck\ -f\ gcc\ % will allow using :make to check the script, and :cnext to jump to the next error.
<file>:<line>:<column>: <type>: <message>
checkstyle
Checkstyle compatible XML output. Supported directly or through plugins by many IDEs and build monitoring systems.
<?xml version='1.0' encoding='UTF-8'?>
<checkstyle version='4.3'>
<file name='file'>
<error
line='line'
column='column'
severity='severity'
message='message'
source='ShellCheck.SC####' />
...
</file>
...
</checkstyle>
diff
Auto-fixes in unified diff format. Can be piped to git apply or patch -p1 to automatically apply fixes. autofix era π₯
--- a/test.sh
+++ b/test.sh
@@ -2,6 +2,6 @@
## Example of a broken script.
for f in $(ls *.m3u)
do
- grep -qi hq.*mp3 $f \
+ grep -qi hq.*mp3 "$f" \
&& echo -e 'Playlist $f contains a HQ file in mp3 format'
done
json1
Json is a popular serialization format that is more suitable for web applications. ShellCheck's json is compact and contains only the bare minimum. Tabs are counted as 1 character.
{
comments: [
{
"file": "filename",
"line": lineNumber,
"column": columnNumber,
"level": "severitylevel",
"code": errorCode,
"message": "warning message"
},
...
]
}
json
This is a legacy version of the json1 format. It's a raw array of comments, and all offsets have a tab stop of 8. it's giving "we keep it around for the old heads", respect π«Ά
quiet
Suppress all normal output. Exit with zero if no issues are found, otherwise exit with one. Stops processing after the first issue. she's blunt, she's efficient, she ate.
π DIRECTIVES π
ShellCheck directives can be specified as comments in the shell script. If they appear before the first command, they are considered file-wide. Otherwise, they apply to the immediately following command or block:
# shellcheck key=value key=value
command-or-structure
For example, to suppress SC2035 about using ./*.jpg:
# shellcheck disable=SC2035
echo "Files: " *.jpg
To tell ShellCheck where to look for an otherwise dynamically determined file:
# shellcheck source=./lib.sh
source "$(find_install_dir)/lib.sh"
Here a shell brace group is used to suppress a warning on multiple lines:
# shellcheck disable=SC2016
{
echo 'Modifying $PATH'
echo 'PATH=foo:$PATH' >> ~/.bashrc
}
Valid keys are:
disableβ Disables a comma separated list of error codes for the following command. The command can be a simple command likeecho foo, or a compound command like a function definition, subshell block or loop. A range can be be specified with a dash, e.g.disable=SC3000-SC4000to exclude 3xxx. All warnings can be disabled withdisable=all.enableβ Enable an optional check by name, as listed with--list-optional. Only file-wide enable directives are considered.extended-analysisβ Set totrue/falseto enable/disable dataflow analysis. Specifying# shellcheck extended-analysis=falsein particularly large (2000+ line) auto-generated scripts will reduce ShellCheck's resource usage at the expense of certain checks. Extended analysis is enabled by default.external-sourcesβ Set totruein.shellcheckrcto always allow ShellCheck to open arbitrary files from'source'statements (the way most tools do).
This option defaults to false only due to ShellCheck's origin as a remote service for checking untrusted scripts. It can safely be enabled for normal development.
sourceβ Overrides the filename included by asource/.statement. This can be used to tellshellcheckwhere to look for a file whose name is determined at runtime, or to skip a source by telling it to use/dev/null.source-pathβ Add a directory to the search path forsource/.statements (by default, only ShellCheck's working directory is included). Absolute paths will also be rooted in these paths. The special pathSCRIPTDIRcan be used to specify the currently checked script's directory, as insource-path=SCRIPTDIRorsource-path=SCRIPTDIR/../libs. Multiple paths accumulate, and-Ptakes precedence over them.shellβ Overrides the shell detected from the shebang. This is useful for files meant to be included (and thus lacking a shebang), or possibly as a more targeted alternative to'disable=SC2039'.
okay that's the whole first half, don't close the tab yet because there is MORE π
π RC FILES π
Unless you pass --norc, bestie, ShellCheck goes on a lil treasure hunt π΅οΈβοΈ β it looks for a file called .shellcheckrc or shellcheckrc in the script's own directory, and then in every parent directory going up. If it finds one, it reads the key=value pairs inside and treats them as file-wide directives. Slay.
Here's a whole example .shellcheckrc so you can see the vibe:
# Look for 'source'd files relative to the checked script,
# and also look for absolute paths in /mnt/chroot
source-path=SCRIPTDIR
source-path=/mnt/chroot
# Since 0.9.0, values can be quoted with '' or "" to allow spaces
source-path="My Documents/scripts"
# Allow opening any 'source'd file, even if not specified as input
external-sources=true
# Turn on warnings for unquoted variables with safe values
enable=quote-safe-variables
# Turn on warnings for unassigned uppercase variables
enable=check-unassigned-uppercase
# Allow [ ! -z foo ] instead of suggesting -n
disable=SC2236
So if there's no .shellcheckrc anywhere in the parent directories, ShellCheck keeps looking β first in ~/.shellcheckrc, then in $XDG_CONFIG_HOME (which is usually ~/.config/shellcheckrc) on Unix, or %APPDATA%/shellcheckrc on Windows. And heads up: only the first file it finds gets used. One and done, periodt. π
Snap girlies listen up π«Ά β the Snap sandbox won't let ShellCheck touch hidden files. So use shellcheckrc without the dot. The dot is the problem, not you.
Docker besties π¦</> β ShellCheck can only peek at files that are actually mounted into the container, so ~/.shellcheckrc is just not gonna be read. Sad but true.
π± ENVIRONMENT VARIABLES π±
You can set the environment variable SHELLCHECK_OPTS with your default flags, like so:
export SHELLCHECK_OPTS='--shell=bash --exclude=SC2016'
Its value gets split on spaces and prepended to the command line every single time you invoke ShellCheck. Every. Single. Time. π
π¦ RETURN VALUES π¦
ShellCheck speaks in exit codes, and here's the whole translation guide:
0β every file scanned successfully, zero issues. Flawless. No notes. π1β every file scanned successfully, but some issues showed up. (Still scanned them all though! That's the win.)2β some files just could not be processed (like, say,file not found). π«3β ShellCheck was invoked with bad syntax (cough, unknown flag, cough). π4β ShellCheck was invoked with bad options (like an unknown formatter, bestie, what did you type).
π LOCALE π
This version of ShellCheck is only available in English, sorry to all my multilingual icons. π
All files get leniently decoded as UTF-8, and if there are invalid sequences it falls back to ISO-8859-1. LC_CTYPE is respected for output, and it defaults to UTF-8 for locales where the encoding isn't specified (like the C locale).
Windows girlies π β if you're seeingcommitBuffer: invalid argument (invalid character), set your terminal to use UTF-8 withchcp 65001. That's the fix, you're welcome. π
π§© KNOWN INCOMPATIBILITIES π§©
(If literally nothing in this section makes sense to you, you are so unlikely to be affected by any of it. Carry on, babe.)
To avoid confusing and misguided suggestions, ShellCheck requires function bodies to be either { brace groups; } or ( subshells ) β no in-between nonsense. And function names containing []*=! are only recognized after a function keyword.
So these two unconventional function definitions? Identical in Bash, but ShellCheck only recognizes the second one:
[x!=y] () [[ $1 ]]
function [x!=y] () { [[ $1 ]]; }
Shells without the function keyword don't even allow those characters in function names in the first place. And function names containing {}? Not supported at all. Nope. Not happening. π
Also, if ShellCheck sees [x!=y] it will assume you meant an invalid comparison. So if you wanna actually invoke that function above, quote the command like '[x!=y]', or β if you wanna keep the same globbing behavior β use command [x!=y].
ShellCheck also puts extra restrictions on the [ command to help catch common invalid uses. Like, POSIX says [ $x= 1 ] is defined, but ShellCheck will assume you actually meant the way more likely comparison [ "$x" = 1 ] and fail accordingly. For unconventional or dynamic uses of the [ command, use test or \[ instead. π«‘
π REPORTING BUGS π
Found a bug? Got an issue? Take it to GitHub, bestie:
https://github.com/koalaman/shellcheck/issues
π AUTHORS π
ShellCheck is developed and maintained by Vidar Holen, with assistance from a long list of wonderful contributors. Absolute icons, every one of them. π«Ά
βοΈ COPYRIGHT βοΈ
Copyright 2012-2025, Vidar Holen and contributors. Licensed under the GNU General Public License version 3 or later, see https://gnu.org/licenses/gpl.html
π SEE ALSO π
sh(1), bash(1), dash(1), ksh(1)
and that's the whole page, bestie!! β¨ This one's the Shell script analysis tool β that's the source name right there in the footer β and it lives at SHELLCHECK(1) in the manuals. Section 1, the user commands, where it belongs. π¦ Go forth and lint, you absolute main character. ππΈ
π¦ where this page comes from
- ubuntu resolute: shellcheck 0.11.0-2 Β· GPL-3.0-or-later
- ubuntu stonking: shellcheck 0.11.0-2 Β· GPL-3.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms