Skip to content
shellhacks.dev
Debugging

Check syntax without running

Check a script for syntax errors without running it using bash -n. It finds an unclosed if, but not a misspelled command or a missing file.

1 min read
Summarize in AI

A deploy script was edited by hand, and you want to know that it parses before it touches anything.

Shell
cat > broken.sh <<'EOF'
#!/bin/bash
if [ -f /etc/os-release ]; then
  echo "found"
EOF
cat > typo.sh <<'EOF'
#!/bin/bash
ecoh "this command does not exist"
EOF
bash -n broken.sh; echo "broken.sh: $?"
bash -n typo.sh; echo "typo.sh: $?"
bash typo.sh; echo "run typo.sh: $?"
Text
broken.sh: line 4: syntax error: unexpected end of file
broken.sh: 2
typo.sh: 0
typo.sh: line 2: ecoh: command not found
run typo.sh: 127

With -n Bash reads and parses the commands but executes none of them, so a missing fi is reported with a line number and the exit status is 2, as the set builtin documentation explains for noexec. The second file parses cleanly, because a misspelled command name is a valid command to the parser, and only the real run finds it.

The check cannot see runtime failures, unset variables or bad paths, so treat it as the first and cheapest gate, and follow it with ShellCheck. It parses only the file itself, and a sourced file is not read. Do not use set -n in a long running interactive shell, since it also stops later commands.

Share

More snippets

Debugging

Stop on the first error and show where

Report where a script failed with trap '...' ERR and set -E. LINENO gives the line, BASH_COMMAND the command and $? the status, even inside functions.

1 min read
Debugging

Print each line as it is read

Print every script line as the shell reads it, before expansion, with set -v. Pair it with set -x to see the source line and the expanded command.

1 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.