Whitespace Matters: Avoiding Syntax Errors In Bash Conditionals
Bash conditionals allow scripts to make decisions and execute code conditionally based on the status of files, variables, and other criteria. However, these powerful tools come with rigid syntax rules that are easy to violate if spacing is not meticulous.
Innocent-looking spaces, tabs, and trailing whitespace can lead to frustrating errors that cause bash scripts to fail unexpectedly. Understanding the specific spacing needs of bash conditionals helps avoid tricky-to-spot syntax mistakes that lead to headaches down the road.
When Spaces Matter
Bash features two types of conditionals: double bracket [[ ]] and single bracket [ ]. The double bracket [[ ]] style offers extended features but comes with stricter spacing rules.
Inside [[ ]] conditionals, spaces are required to delimit words and operators. Missing spaces lead to syntax failures that aren’t always easy to decipher. For example:
[[$foo==bar]] → Fails [[ $foo == bar ]] → Works
The first example fails because the variables and operators run together without spaces. When corrected with spaces in the second line, it works as expected.
The single bracket [ ] style conditionals are more permissive about spacing but have limitations compared to [[ ]]. Spaces are allowed but not required around variables and operators in [ ]. However, mixing the two styles can cause problems, for example:
[ [$foo == bar] ] → Fails [[ $foo == bar ]] → Works
Putting a [[ ]] conditional inside a [ ] conditional fails because the inner [[ ]] imposes whitespace rules that conflict with the leniency of [ ].
Tidy Up Stray Whitespace
Bash syntax requires careful attention to stray whitespace both inside and around conditionals. Trailing whitespace after the opening [[ or closing ]] brackets causes cryptic errors:
[[ $foo == bar ]] → Fails [[$foo == bar]]→ Fails [[ $foo == bar]] → Fails
Each of the above fails due to subtle trailing whitespace after a bracket. The error messages may be obtuse, for example referencing an unexpected token or premature end of file.
Best practice is to eliminate all trailing whitespace which could touch up against brackets and violate bash parsing rules. Consistent indentation that avoids extra whitespace touching brackets helps avoid such problems.
Use Tabs Deliberately
Bash interprets tabs differently from spaces, so mixing the two can lead to unexpected errors. Consider this conditional:
[[ $foo == bar ]] → Fails
What appears to be a space before the == is actually a tab character. Because tabs have different width rules than spaces, this breaks the syntax even though it looks correct.
Here is a corrected version with consistent leading spaces:
[[ $foo == bar ]] → Works
Use spaces or tabs consistently, avoid mixing them, and use tab expansion features in text editors to reveal hard-to-see tabs.
Spot Check Your Scripts
Linting tools like shellcheck help automatically scan scripts to detect issues with conditionals and other bash syntax. For tricky spacing issues, try visually inspecting conditionals in text editors to see if any problematic whitespace touches the brackets.
Many code and text editors have whitespace display modes that make spaces, tabs and trailing whitespace visible. These help spot gremlins like trailing whitespace that silently break syntax.
Take Control Of Spacing
Bash conditional syntax is notoriously finicky when it comes to whitespace. Gaining control over spacing in and around conditionals prevents many frustrating issues down the line. Learn the strict spacing rules for [[ ]], avoid trailing whitespace, and use consistent indentation to head off troublesome syntax errors.
With careful attention to spacing details, bash conditionals can robustly power scripts to accomplish complex tasks without subtle issues plaguing progress.