5

The following shell script executes well when provided /bin/true for the first argument, but may otherwise fail with a syntax error during execution!

#!/bin/sh
if $1 ; then exit; fi
/tmp/asdf <<< ASDF # Something with syntax error in POSIX

Surely some syntax errors (if not all?) can be avoided by static checking? How do I statically check whether a given Shell Command Language script is syntactically valid?

EDIT: Checking for syntax errors in Bash scripts has been answered in this question.

EDIT #2: Note that Bash fails to properly check whether the syntax adheres to POSIX even when executed with the +B and --posix flags in addition to -n.

Community
  • 1
  • 1
mceo
  • 1,221
  • 11
  • 18
  • 4
    http://shellcheck.net is a useful resource and as I recall you can download a standalone tool. – Tom Fenech Apr 27 '16 at 10:39
  • 1
    @tripleee Please reconsider whether this really is a duplicate. – mceo Apr 27 '16 at 12:41
  • The duplicate asks for a Bash solution but the answers are fine for POSIX, too. The duplicate link could go the other way if the shellcheck.net answer is migrated here, but I don't really see the need -- this duplicate works as a signpost for people searching for a POSIX solution. – tripleee Apr 27 '16 at 16:35
  • 1
    @tripleee Actually this question appears to be more of a duplicate of [this question](https://stackoverflow.com/questions/28654973/test-for-posix-shell-compliance) (which is also a duplicate of [this one on Unix&Linux](https://unix.stackexchange.com/questions/48786/how-can-i-test-for-posix-compliance-for-shell-scripts)). – jotik Apr 27 '16 at 16:49
  • @jotik Nominally a better question, but its sole answer is rather unsatisfactory. – tripleee Apr 27 '16 at 17:24
  • The *syntax* is fine; using a parameter expansion to supply an entire command is not. – chepner May 02 '16 at 12:24

2 Answers2

6

All POSIX-compatible Shell Command Language shells support the set -n built-in which can be used to check the syntax of the script. Therefore it is possible to prepend

set -n

to your code to syntax check it. Note also that standard sh utility is also required to support a command-line -n flag, which has equivalent semantics to using set -n. Bash and possibly other shells also support this command-line flag. Therefore you can simply run the following to syntax check your script:

sh -n yourScriptFilename.sh

WARNING: This does not give you a guarantee that the script has fully POSIX compatible syntax. For example, Bash allows bashisms (e.g. arrays and c{a,u}t) to go unnoticed even when using the --posix (and/or +B) command line option in addition to -n when invoked as sh. Other shells might have similar issues.

mceo
  • 1,221
  • 11
  • 18
  • Upvote for for POSIX link. – Jens Apr 27 '16 at 12:45
  • Why do you ask a question and then duplicate what I said in your own answer? Furthermore it is not useful to change a file, add `set -n` on top before you syntax check it and remove that afterwards. Using `-n` as the command line option, as I told, makes much more sense. – hek2mgl Apr 27 '16 at 12:59
  • @hek2mgl Sportsmanship. :-) Note that I didn't accept my own answer, because it doesn't fully answer my question. I urgently need to test a large number of shell scripts for POSIX compatibility (syntax only or as far as possible), which is why I need a reliable means to do it. – mceo Apr 27 '16 at 13:08
  • 1
    Use `bash --posix -n` for that. If you have a *more* posix compatible shell at the hand, check if it is supports the `-n` option as well. `dash` for example supports the `-n` option. – hek2mgl Apr 27 '16 at 13:12
  • 1
    The Debian devscripts ([deb package](https://packages.debian.org/search?keywords=devscripts), [git](https://anonscm.debian.org/cgit/collab-maint/devscripts.git)) contain `checkbashisms` to "check whether a /bin/sh script contains any common bash-specific constructs" (see also [this answer](http://stackoverflow.com/a/3679916/3919155)). – jotik Apr 27 '16 at 16:41
5

With bash you can use -n:

bash -n file.sh

Output:

a.sh: line 3: syntax error near unexpected token `then'
a.sh: line 3: `if then fi # Something with syntax error'

Since bash supports the --posix options you may run

bash --posix -n file.sh

to perform a posix compatible check. I don't know how posixly correct that mode is in detail.

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
  • I assume this only checks for Bash syntax, but not POSIX? – mceo Apr 27 '16 at 10:45
  • Yes, that checks only for bash syntax. However other shells (might) have similar options. `dash` for example supports `-n` as well. Which POSIX shell do you have in mind? – hek2mgl Apr 27 '16 at 10:47
  • 1
    I think the correct term is "[Shell Command Language](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html)". – mceo Apr 27 '16 at 10:51
  • You can run `bash --posix -n` – hek2mgl Apr 27 '16 at 12:34
  • I just amended [my answer](http://stackoverflow.com/a/36888649/6123289) with a warning about Bash not fully respecting `bash --posix -n`. – mceo Apr 27 '16 at 12:35