How do I syntax check a Bash script without running it?
Solution 1
bash -n scriptname
Perhaps an obvious caveat: this validates syntax but won't check if your bash script tries to execute a command that isn't in your path, like ech hello
instead of echo hello
.
Solution 2
Time changes everything. Here is a web site which provide online syntax checking for shell script.
I found it is very powerful detecting common errors.
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!
Solution 3
I also enable the 'u' option on every bash script I write in order to do some extra checking:
set -u
This will report the usage of uninitialized variables, like in the following script 'check_init.sh'
#!/bin/sh
set -u
message=hello
echo $mesage
Running the script :
$ check_init.sh
Will report the following :
./check_init.sh[4]: mesage: Parameter not set.
Very useful to catch typos
Solution 4
sh -n script-name
Run this. If there are any syntax errors in the script, then it returns the same error message.
If there are no errors, then it comes out without giving any message. You can check immediately by using echo $?
, which will return 0
confirming successful without any mistake.
It worked for me well. I ran on Linux OS, Bash Shell.
Solution 5
I actually check all bash scripts in current dir for syntax errors WITHOUT running them using find
tool:
Example:
find . -name '*.sh' -print0 | xargs -0 -P"$(nproc)" -I{} bash -n "{}"
If you want to use it for a single file, just edit the wildcard with the name of the file.
Related videos on Youtube
Tom Feiner
Updated on February 20, 2022Comments
-
Tom Feiner about 2 years
Is it possible to check a bash script syntax without executing it?
Using Perl, I can run
perl -c 'script name'
. Is there any equivalent command for bash scripts?-
blong almost 10 years
-
-
skinp over 15 yearsThanks for the tip, I will definitly use this one. Strangely, this option isn't listed in bash's man page :S...
-
ephemient over 15 yearsIn bash's manpage, under "SHELL BUILTIN COMMANDS / set", -n is documented, and as the beginning of the manpage states, bash interprets all single-character options that
set
does. -
Brynjar almost 13 yearsto add to the (for me) non obvious caveat, it also won't catch an error caused by a missing space
if ["$var" == "string" ]
instead ofif [ "$var" == "string" ]
-
GuruM almost 12 yearsThough not exactly related to bash syntax check - using set -x and set +x for debugging the full script or sections of the script is quite useful
-
zzapper almost 11 yearsThanks for this didn't know didn't know about the -n but what I wanted was @GuruM > sh -x test.sh as that displays the generated output of the script
-
GuruM almost 11 yearsYes. I forgot to mention that you can do the following At command line: 1) bash -x test.sh #this runs the whole script in 'debug mode' 2) set +x; bash test.sh; set -x #set debug mode on/off before/after script run In the script: a) #!/bin/bash -x #add 'debug mode' at top of script b) set +x; code; set -x #add 'debug mode' for any section of script
-
CanadianGirl827x almost 10 years@Brynjar That's because it's just syntax checking. The open bracket isn't syntax, that's the name of the function to run.
type [
says "[ is a shell builtin". It ultimately delegates to thetest
program, but it expects a closing bracket, as well. So it's likeif test"$var"
, which isn't what the author meant, but is syntactically valid (say $var has a value of "a", then we will see "bash: testa: command not found"). Point is that syntactically, there is no missing space. -
mklement0 almost 9 years@JoshuaCheek: Builtin
[
is only invoked in this case if$var
happens to expand to an empty string. If$var
expands to a non-empty string,[
is concatenated with that string and is interpreted as a command name (not function name) by Bash, and, yes, that is syntactically valid, but, as you state, obviously not the intent. If you use[[
instead of[
, even though[[
is a shell keyword (rather than a builtin), you'll get the same result, because the unintended string concatenation still overrides recognition of the keyword. -
mklement0 almost 9 years@JoshuaCheek: Bash is still syntax-checking here: it's checking simple-command invocation syntax:
["$var"
is syntactically a valid command-name expression; similarly, tokens==
and"$string"
are valid command arguments. (Generally, builtin[
is parsed with command syntax, whereas[[
- as a shell keyword - is parsed differently.) The shell builtin[
does not delegate to the "test
program" (external utility):bash
,dash
,ksh
,zsh
all have builtin versions of both[
andtest
, and they do not call their external-utility counterparts. -
mklement0 almost 9 yearsThe bottom line is: using just Bash itself,
-n
is your best bet, but that won't catch many errors beginners are likely to make; to catch these, use shellcheck.net or its CLI, as detailed in dvd818's answer. -
mklement0 almost 9 yearsGreat tip; on OSX you can now also install the shellcheck.net CLI,
shellcheck
, via Homebrew:brew install shellcheck
. -
CanadianGirl827x almost 9 years@mklement0 nice, ty for the great explanation!
-
Alois Mahdal almost 9 yearsAnother caveat: won't take in account options set in script. Eg if you add
shopt -s extglob
and then dofoo@(bar|baz))
incase
,bash -n
will see that as syntax error (bash -s extglob -n
will not, but you never know which part of the script is affected) -
that other guy almost 9 yearsAlso on debian&friends:
apt-get install shellcheck
-
Peterino almost 9 yearsFor Ubuntu trusty this package must be installed from
trusty-backports
. -
μολὼν.λαβέ over 8 yearsi set these flags always in my bash scripts, if it passes these, it's good to go "set -o errexit" "set -o nounset" "set -o pipefail"
-
Greg Dubicki over 7 yearsBut it won't work if your files don't end with
.sh
or other extension associated with Bash scripts, which is the case if you generate the scripts using some templating tool like ERB (then they end with.erb
). Please vote for youtrack.jetbrains.com/issue/IDEA-79574 if you want it fixed! -
zhihong over 7 yearsAs mentioned above, trusty dependency needed, and can install it as below in ubuntu 14.04: sudo apt-get -f install, then: sudo sudo apt-get install shellcheck
-
mug896 about 7 yearsit use parameter expansions
-
rubo77 almost 7 years+1 for
set -u
although this does not really answer the question, because you have to run the script to get the error message. Not evenbash -n check_init.sh
shows that warning -
rubo77 almost 7 yearsthis works, because
set -x
shows every line before it is executed -
Daniel H almost 6 yearsThis is really useful, but it does not use Bash’s parser but its own. In most cases this is good enough and it can identify both parsing and other issues, but there is at least one edge case (and probably others I haven’t seen) where it doesn’t parse quite the same way.
-
Daniel H almost 6 years@AloisMahdal Unfortunately that would be impossible to fix in the general case, since shell options can change mid-script or even based on information that can only be known at runtime.
-
wisbucky about 5 yearsHere's the documentation from
man bash
:-n Read commands but do not execute them. This may be used to check a shell script for syntax errors. This is ignored by interactive shells.
-
qodeninja over 4 yearsis the -n option version or os specific; doesnt seem to work on osx
-
jarno over 4 years
sh -n
will probably not check that the script is valid Bash script. It might give false negatives.sh
is some Bourne shell variant that is usually not Bash. For example in Ubuntu Linuxrealpath -e $(command -v sh)
gives /bin/dash -
Alberto Salvia Novella about 3 yearsIf you want to run your program only if it passes shellcheck: gitlab.com/es20490446e/shellproof