ShellCheck: A static analysis tool for shell scripts

Last modified on March 19, 2021
Build Status

ShellCheck is a GPLv3 machine that provides warnings and options for bash/sh shell scripts:

Screenshot of a terminal showing problematic shell script lines highlighted

The goals of ShellCheck are

  • To current and elaborate widespread beginner's syntax components that house off a shell
    to provide cryptic error messages.

  • To current and elaborate widespread intermediate stage semantic concerns that
    house off a shell to behave unusually and counter-intuitively.

  • To current delicate caveats, nook instances and pitfalls that may house off an
    developed particular person's in every other case working script to fail underneath future conditions.

Glimpse the gallery of tainted code for examples of what ShellCheck will allow you to determine!

Table of Contents

  • train
    • On the secure
    • From your terminal
    • On your editor
    • On your make or check suites
  • Installing
  • Compiling from supply
    • Installing Cabal
    • Compiling ShellCheck
    • Running exams
  • Gallery of tainted code
    • Quoting
    • Conditionals
    • Often misused directions
    • Fashioned beginner's errors
    • Model
    • Recordsdata and typing errors
    • Robustness
    • Portability
    • Miscellaneous
  • Testimonials
  • Ignoring components
  • Reporting bugs
  • Contributing
  • Copyright
  • A lot of Resources


There are a collection of techniques to make train of ShellCheck!

On the secure

Paste a shell script on for on the spot suggestions. is frequently synchronized to primarily the most recent git commit, and is totally essentially the most life like system to provide ShellCheck a poke. Expose your pals!

From your terminal

Stride shellcheck yourscript for your terminal for on the spot output, as considered above.

On your editor

You would respect ShellCheck options straight in a spread of editors.

  • Vim, through ALE, Neomake, or Syntastic:

Screenshot of Vim showing inlined shellcheck feedback.

  • Emacs, through Flycheck or Flymake:

Screenshot of emacs showing inlined shellcheck feedback.

  • Sublime, through SublimeLinter.

  • Atom, through Linter.

  • VSCode, through vscode-shellcheck.

  • Most different editors, through GCC error compatibility.

On your make or check suites

Whereas ShellCheck is principally meant for interactive train, it may possibly with out issues be added to builds or check suites.
It makes canonical train of exit codes, in order that it's potential you may possibly presumably excellent add a shellcheck instruct as part of the method.

As an illustration, in a Makefile:

    # Fail if any of those information have warnings
    shellcheck myscripts/*.sh

or in a Travis CI .travis.yml file:

  # Fail if any of those information have warnings
  - shellcheck myscripts/*.sh

Services and merchandise and platforms which have ShellCheck pre-place in and fascinating to make train of:

  • Travis CI
  • Codacy
  • Code Climate
  • Code Ingredient
  • CircleCI through the ShellCheck Orb
  • Github (handiest Linux)

Services and merchandise and platforms with third celebration plugins:

  • SonarQube through sonar-shellcheck-plugin

Most different suppliers and merchandise, together with GitLab, allow you to arrange
ShellCheck your self, both through the machine's gear supervisor (respect Installing),
or by downloading and unpacking a binary begin.

Or not it's a elegant thought to manually arrange a selected ShellCheck model regardless. This avoids
any shock make breaks when a model unique model with unique warnings is printed.

For customized filtering or reporting, ShellCheck can output easy JSON, CheckStyle like minded XML,
GCC like minded warnings as successfully as human readable textual declare materials (with or with out ANSI colours). Glimpse the
Integration wiki web page for added documentation.


The most life like system to arrange ShellCheck domestically is through your gear supervisor.

On techniques with Cabal (installs to ~/.cabal/bin):

cabal substitute
cabal arrange ShellCheck

On techniques with Stack (installs to ~/.native/bin):

stack substitute
stack arrange ShellCheck

On Debian primarily primarily based distros:

actual-obtain arrange shellcheck

On Arch Linux primarily primarily based distros:

pacman -S shellcheck

or get hold of the dependency free shellcheck-bin from the AUR.

On Gentoo primarily primarily based distros:

emerge --demand shellcheck

On EPEL primarily primarily based distros:

yum -y arrange epel-start
yum arrange ShellCheck

On Fedora primarily primarily based distros:

dnf arrange ShellCheck

On FreeBSD:

pkg arrange hs-ShellCheck

On macOS (OS X) with Homebrew:

brew arrange shellcheck

Or with MacPorts:

sudo port arrange shellcheck

On OpenBSD:

pkg_add shellcheck

On openSUSE

zypper in ShellCheck

Or train OneClickInstall -

On Solus:

eopkg arrange shellcheck

On Windows (through chocolatey):

C:> choco arrange shellcheck

Or Windows (through scoop):

C:> scoop arrange shellcheck

From conda-forge:

conda arrange -c conda-forge shellcheck

From Snap Store:

snap arrange --channel=edge shellcheck

From Docker Hub:

docker flee --rm -v "$PWD:/mnt" koalaman/shellcheck:steady myscript
# Or :v0.4.7 for that model, or :newest for day after day builds

or train koalaman/shellcheck-alpine everytime you occur to choose to have a nearer Alpine Linux primarily primarily based picture to elongate. It really works precisely fancy a traditional Alpine picture, however has shellcheck preinstalled.

Utilizing the nix gear supervisor:

nix-env -iA nixpkgs.shellcheck

Alternatively, it's potential you may possibly presumably obtain pre-compiled binaries for primarily the most recent begin proper right here:

  • Linux, x86_64 (statically linked)
  • Linux, armv6hf, i.e. Raspberry Pi (statically linked)
  • Linux, aarch64 aka ARM64 (statically linked)
  • macOS, x86_64
  • Windows, x86

or respect the GitHub Releases for different releases
(together with primarily the most recent meta-start for day after day git builds).

Distro packages already include a man web page. While you occur to are constructing from supply, it would possibly possibly be place in with:

pandoc -s -f markdown-effectively-organized -t man -o shellcheck.1
sudo mv shellcheck.1 /usr/fragment/man/man1

Travis CI

Travis CI has now built-in ShellCheck by default, so that you just simply do not should manually arrange it.

While you occur to proceed to should attain so in notify to pork up at your leisure or type creep you're
the train of primarily the most recent begin, observe the steps underneath to arrange a binary model.

Installing a pre-compiled binary

The pre-compiled binaries are available in tar.xz information. To decompress them, be decided
xz is place in.
On Debian/Ubuntu/Mint, it's potential you may possibly presumably precise arrange xz-utils.
On Redhat/Fedora/CentOS, yum -y arrange xz.

A easy installer may possibly possibly nicely attain one factor fancy:

scversion="steady" # or "v0.4.7", or "newest"
wget -qO- "${scversion?}/shellcheck-${scversion?}.linux.x86_64.tar.xz" | tar -xJv
cp "shellcheck-${scversion}/shellcheck" /usr/bin/
shellcheck --version

Compiling from supply

This piece describes be taught the plan wherein to make ShellCheck from a supply listing. ShellCheck is written in Haskell and requires 2GB of RAM to compile.

Installing Cabal

ShellCheck is constructed and packaged the train of Cabal. Set up the gear cabal-set up out of your machine's gear supervisor (with e.g. actual-obtain, brew, emerge, yum, or zypper).

On macOS (OS X), it's potential you may possibly presumably attain a on the spot arrange of Cabal the train of brew, which takes a short while instead of extra than 30 minutes everytime you occur to attempt to compile it from supply.

$ brew arrange cabal-set up

On MacPorts, the gear is as a substitute referred to as hs-cabal-set up, whereas native Windows prospects may possibly possibly nicely soundless arrange primarily the most recent model of the Haskell platform from

Test that cabal is place in and substitute its dependency guidelines with

$ cabal substitute

Compiling ShellCheck

git clone this repository, and cd to the ShellCheck supply listing to make/arrange:

$ cabal arrange

Or everytime you occur to suggest to flee the exams:

$ cabal arrange --enable-exams

This would possibly compile ShellCheck and arrange it to your ~/.cabal/bin listing.

Add this listing to your PATH (for bash, add this to your ~/.bashrc):

export PATH="$HOME/.cabal/bin: $PATH"

Log inside and out once more, and examine that your PATH is house up exactly:

$ which shellcheck

On native Windows, the PATH may possibly possibly nicely soundless already be house up, nonetheless the machine
may possibly possibly nicely train a legacy codepage. In cmd.exe, powershell.exe and Powershell ISE,
be creep you make train of a TrueType font, not a Raster font, and house the filled with life
codepage to UTF-8 (65001) with chcp:

In Powershell ISE, it's potential you may possibly presumably should moreover substitute the output encoding:

[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

Running exams

To flee the unit check suite:

$ cabal check

Gallery of tainted code

So what roughly issues does ShellCheck search? Right right here is an incomplete guidelines of detected components.


ShellCheck can acknowledge a number of sorts of unsuitable quoting:

echo $1                           # Unquoted variables
get hold of . -identify *.ogg                # Unquoted get hold of/grep patterns
rm "~/my file.txt"                # Quoted tilde development
v='--verbose="moral"'; cmd $v      # Literal quotes in variables
for f in "*.ogg"                  # Incorrectly quoted 'for' loops
contact $@                          # Unquoted $@
echo 'Don't disregard to restart!'   # Singlequote closed by apostrophe
echo 'Don't do this at dwelling'    # Making an try and flee ' in ''
echo 'Route is $PATH'              # Variables in single quotes
entice "echo Took ${SECONDS}s" 0    # Upfront expanded entice


ShellCheck can acknowledge many sorts of unsuitable check statements.

[[ n != 0 ]]                      # Constant check expressions
[[ -e *.mpg ]]                    # Existence exams of globs
[[ $foo==0 ]]                     # Often moral which capacity of missing areas
[[ -n "$foo " ]]                  # Often moral which capacity of literals
[[ $foo =~ "fo+" ]]               # Quoted regex in=~
[ foo =~ re ]                     # Unsupported [ ] operators
[ $1 -eq "shellcheck" ]           # Numerical comparability of strings
[ $n && $m ]                      # && in [ .. ]
[ grep -q foo file ]              # Record with out $(..)
[[ "$$file" == *.jpg ]]           # Comparisons that may not succeed
(( 1 -lt 2 ))                     # Utilizing check operators in ((..))

Often misused directions

ShellCheck can acknowledge conditions the place directions are dilapidated incorrectly:

grep '*foo*' file                 # Globs in regex contexts
get hold of . -exec foo {} && bar {} ;  # Upfront terminated get hold of -exec
sudo echo 'Var=42' > /and so forth/profile # Redirecting sudo
time --format=%s sleep 10         # Passing time(1) flags to time builtin
whereas be taught h; attain ssh "$h" uptime  # Instructions consuming whereas loop enter
alias archive='mv $1 /backup'     # Defining aliases with arguments
tr -cd '[a-zA-Z0-9]'              # [] spherical ranges in tr
exec foo; echo "Performed!"            # Misused 'exec'
get hold of -identify *.bak -o -identify *~ -delete  # Implicit priority in get hold of
# get hold of . -exec foo> bar ;       # Redirections in get hold of
f() { whoami; }; sudo f           # Exterior train of inside features

Fashioned beginner's errors

ShellCheck acknowledges many neatly-liked beginner's syntax errors:

var=42                          # Spaces spherical=in assignments
$foo=42                           # $ in assignments
for $var in *; attain ...             # $ in for loop variables
var$n="Hello"                     # Pass oblique task
echo ${var$n}                     # Pass oblique reference
var=(1, 2, 3)                     # Comma separated arrays
array=( [index]=price )         # Unsuitable index initialization
echo $var[14]                     # Lacking {} in array references
echo "Argument 10 is $10"         # Positional parameter misreference
if $(myfunction); then ..; fi     # Wrapping directions in $()
else if othercondition; then ..   # Utilizing 'else if'
f; f() { echo "hello there world; }     # Utilizing characteristic ahead of definition
[ false ]                         # 'false' being moral
if ( -f file )                    # Utilizing (..) instead of check


ShellCheck can type options to pork up mannequin:

[[ -z $(find /tmp | grep mpg) ]]  # Spend grep -q as a substitute
a >> log; b >> log; c >> log      # Spend a redirection block as a substitute
echo "The time is `date`"         # Spend $() as a substitute
cd dir; task *; cd ..;         # Spend subshells as a substitute
echo $[1+2]                       # Spend widespread $((..)) instead of ragged $[]
echo $(($RANDOM % 6))             # Execute not train $ on variables in $((..))
echo "$(date)"                    # Ineffective train of echo
cat file | grep foo               # Ineffective train of cat

Recordsdata and typing errors

ShellCheck can acknowledge components associated to recordsdata and typing:

args="$@"                         # Assigning arrays to strings
information=(foo bar); echo "$information"    # Referencing arrays as strings
say -A arr=(foo bar)          # Associative arrays with out index
printf "%sn" "Arguments: $@."    # Concatenating strings and arrays
[[ $# > 2 ]]                      # Comparing numbers as strings
var=World; echo "Hello " var      # Unused lowercase variables
echo "Hello $determine"                # Unassigned lowercase variables
cmd | be taught bar; echo $bar         # Assignments in subshells
cat foo | cp bar                  # Piping to directions that do not be taught
printf '%s: %sn' foo             # Mismatches in printf argument depend


ShellCheck can type options for bettering the robustness of a script:

rm -rf "$STEAMROOT/"*            # Catastrophic rm
contact ./-l; ls *                 # Globs that may possibly nicely grew to become alternate options
get hold of . -exec sh -c 'a && b {}' ; # Earn -exec shell injection
printf "Hello $determine"             # Variables in printf format
for f in $(ls *.txt); attain         # Iterating over ls output
export MYVAR=$(cmd)              # Masked exit codes
case $model in 2.*) : ;; 2.6.*) # Shadowed case branches


ShellCheck will warn when the train of features not supported by the shebang. As an illustration, everytime you occur to house the shebang to #!/bin/sh, ShellCheck will warn about portability components equal to checkbashisms:

echo {1..$n}                     # Works in ksh, however not bash/hurry/sh
echo {1..10}                     # Works in ksh and bash, however not hurry/sh
echo -n 42                       # Works in ksh, bash and hurry, undefined in sh
entice 'exit 42' sigint            # Unportable sign spec
cmd &> file                      # Unportable redirection operator
be taught foo  /dev/tcp/host/22      # Unportable intercepted information
foo-bar() { ..; }                # Undefined/unsupported operate title
[ $UID = 0 ]                     # Variable undefined in sprint/sh
native var=worth                  # native is undefined in sh
time sleep 1 | sleep 5           # Undefined makes use of of 'time'


ShellCheck acknowledges a menagerie of different points:

PS1='e[0;32m$e[0m '            # PS1 colors not in [..]
PATH="$PATH:~/bin"                # Literal tilde in $PATH
rm “file”                         # Unicode quotes
echo "Hello world"                # Carriage return / DOS line endings
echo hi there                       # Trailing areas after 
var=42 echo $var                  # Expansion of inlined surroundings
#!/bin/bash -x -e                 # Common shebang errors
echo $((n/180*100))               # Unnecessary lack of precision
ls *[:digit:].txt                 # Bad character class globs
sed 's/foo/bar/' file > file      # Redirecting to enter
whereas getopts "a" f; attain case $f in "b") # Unhandled getopts flags


To begin out with you're fancy "shellcheck is nice" however then you definitely definately are fancy "wtf are we soundless the train of bash"

Alexander Tarasikov,
through Twitter

Ignoring components

Complications may possibly be missed through environmental variable, instruct line, individually or globally inside a file:

Reporting bugs

Please train the GitHub iss

Read More

Similar Products:

    None Found

Recent Content