About ShellCheck

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!

Run ShellCheck online

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

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

Run ShellCheck locally

If you download and compile the source code, you get a pretty terminal frontend!

With cabal installed, you can also install the latest stable release with cabal install shellcheck

Run ShellCheck in your editor

ShellCheck can output gcc style error messages and checkstyle compatible xml, which allows any editor to show inlined error messages.

It's also supported directly by Syntastic in Vim and Flycheck in Emacs.

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 ]
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
$ 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

More fun stuff

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