About ShellCheck

This page has been deprecated! Please see github.com/koalaman/shellcheck for updated information!

ShellCheck is a static analysis and linting tool for sh/bash scripts. It's mainly focused on handling typical beginner and intermediate level syntax errors and pitfalls where the shell just gives a cryptic error message or strange behavior, but it also reports on a few more advanced issues where corner cases can cause delayed failures.

Haskell source code is available on GitHub!

Try ShellCheck online

Go to ShellCheck.net to copy-paste a shell script and get immediate, automatic feedback. Tell your friends!

The online version is always synced against the latest git commit.

Install ShellCheck locally

ShellCheck is available through your package manager! Install it with cabal/apt-get/yum/brew to get a pretty terminal front-end!

Run ShellCheck in your editor

If you install both shellcheck and either Syntastic for Vim or Flycheck for Emacs, you'll get feedback straight in your editor!

Also supported by Sublime and Atom, and pretty much any IDE thanks to gcc compatible error messages.

What does ShellCheck check?

Here is an incomplete list of things ShellCheck warns about and suggests improvements to:

Unquoted globs for find/grep
find . -name *.ogg
Constant test expressions
[[ n != 0 ]]
Assigning arrays to strings
Redirecting into source file
sed -e 's/foo/bar/g' file > file
Existence checks of globs
[[ -e *.mpg ]]
Globs in regex context
grep '*foo*' file
PS1 colors not in \[..\]
PS1='\e[0;32m\$\e[0m '
Prematurely terminated find -exec
find / -exec touch {} && echo {} \;
Literal quotes in arguments
cmd $verbose
Assignment in subshells
echo foo | read bar
echo $bar
Confusing time(1) for builtin
time --format=%s sleep 10
~ in quotes
rm "~/my file.txt"
Single, quoted 'for' argument
for f in "*.ogg"
do rm $f; done
Arithmetic truncation
echo $((n/180*100))
Functions used externally
f() { rm file; }; sudo f
Unused variables
var=World; echo "Hello " var
Looping over ls output
for f in $(ls *.ogg)
do ...; done
Arguments in aliases
alias archive='mv $1 /backup'
Referencing arrays as strings
files=(foo bar); echo "$files"
Unquoted command expansion
tar cf file$(date).tar dir
$ in for loop variables
for $var in foo bar baz; do echo "$var"; done
Unquoted $@
touch $@
Unicode quotes
rm “file”
Attempted redirection of stdout+stderr
cmd 2>&1 > /dev/null
Attempted indirect assignment
Attempted indirect reference
echo ${var$n}
Variables in single quotes
echo 'Path is $PATH'
Comparing numbers with < or >
[[ $n > 0 ]]
Unsupported [ ] operators
[ foo =~ re ]
Using ~ in $PATH
Quoted =~ regex
[[ $foo =~ "fo+" ]]
Opportunities for grep -q
[[ -z $(find /tmp | grep mpg) ]]
Tautology due to spacing
[[ $foo==0 ]]
Variable brace expansion (Bash)
echo {1..$n}
Commands eating loop input
while read host; do ssh "$host" uptime; done < file
Decimals arithmetics
echo $((3.14*r*r))
Comma separated arrays
var=(1, 2, 3)
Misused 'exec'
exec foo; echo "Done!"
Globs that could become options
touch ./-l; ls *
Common shebang errors
#!/bin/bash -x -e
Variables in printf format
printf "Hello $name"
Numerical comparison of strings
[[ $1 -eq "shellcheck" ]]
Prefix assignments in args
var=42 echo $var
Implicit precedence in find
find . -name '*.bak' -o -name '*~' -delete
Useless use of echo
echo $(date)
Repetitive redirections
cmd1 >> file; cmd2 >> file; cmd3 >> file;
Redirecting sudo
sudo echo 'alias sl=ls' >> /etc/profile
[] around ranges in tr
tr '[a-z]' '[A-Z]'
Misquoted traps
trap "echo \"Runtime: ${SECONDS}s\"" exit
&& in [ .. ]
[ $n && $m ]
Masked return values
export var="$(myfunc)"
Singlequote closed by apostrophe
echo 'Don't forget to run foo --update!'
Attempting to escape ' in ''
var='Don\'t try this at home'
Misused char class globs
ls *[:digit:].txt
Concatenating strings and arrays.
printf "%s\n" "Command line was $@."
Positional parameter misreference
echo "Argument 10 is $10"
cd-and-back antipattern
for d in *; do cd "$d"; cmd; cd ..; done
Missing semicolons in loops
for f in *.mp3 do true; done
Catastrophic rm
rm -rf "$STEAMROOT/"*
$ in assignments
Aliases expanding early
alias whereami="echo $PWD"
Spaces in assignment
var = 42
Features shebang may not support
echo {1..10}
Excessive $()/``
cmd='echo foo'; `$cmd`;

What people are saying

At first you're like "shellcheck is awesome" but then you're like "wtf are we still using bash"

— Alexander Tarasikov (@astarasikov) February 20, 2015

How to report bugs and issues

Bugs, issues and feature suggestions can be filed on Github

More fun stuff

For more fun stuff, see the author's home page!.