How do I syntax check a Bash script without running it?

255,768

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.

enter image description here

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.

Share:
255,768

Related videos on Youtube

Tom Feiner
Author by

Tom Feiner

Updated on February 20, 2022

Comments

  • Tom Feiner
    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?

  • skinp
    skinp over 15 years
    Thanks for the tip, I will definitly use this one. Strangely, this option isn't listed in bash's man page :S...
  • ephemient
    ephemient over 15 years
    In 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
    Brynjar almost 13 years
    to add to the (for me) non obvious caveat, it also won't catch an error caused by a missing space if ["$var" == "string" ] instead of if [ "$var" == "string" ]
  • GuruM
    GuruM almost 12 years
    Though 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
    zzapper almost 11 years
    Thanks 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
    GuruM almost 11 years
    Yes. 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
    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 the test program, but it expects a closing bracket, as well. So it's like if 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
    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
    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 [ and test, and they do not call their external-utility counterparts.
  • mklement0
    mklement0 almost 9 years
    The 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
    mklement0 almost 9 years
    Great tip; on OSX you can now also install the shellcheck.net CLI, shellcheck, via Homebrew: brew install shellcheck.
  • CanadianGirl827x
    CanadianGirl827x almost 9 years
    @mklement0 nice, ty for the great explanation!
  • Alois Mahdal
    Alois Mahdal almost 9 years
    Another caveat: won't take in account options set in script. Eg if you add shopt -s extglob and then do foo@(bar|baz)) in case, 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
    that other guy almost 9 years
    Also on debian&friends: apt-get install shellcheck
  • Peterino
    Peterino almost 9 years
    For Ubuntu trusty this package must be installed from trusty-backports.
  • μολὼν.λαβέ
    μολὼν.λαβέ over 8 years
    i 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
    Greg Dubicki over 7 years
    But 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
    zhihong over 7 years
    As 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
    mug896 about 7 years
    it use parameter expansions
  • rubo77
    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 even bash -n check_init.sh shows that warning
  • rubo77
    rubo77 almost 7 years
    this works, because set -x shows every line before it is executed
  • Daniel H
    Daniel H almost 6 years
    This 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
    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
    wisbucky about 5 years
    Here'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
    qodeninja over 4 years
    is the -n option version or os specific; doesnt seem to work on osx
  • jarno
    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 Linux realpath -e $(command -v sh) gives /bin/dash
  • Alberto Salvia Novella
    Alberto Salvia Novella about 3 years
    If you want to run your program only if it passes shellcheck: gitlab.com/es20490446e/shellproof