Bash Anti-Patterns Overview
Bash Anti-Patterns Overview
Not Quoting Variables
Not Quoting Variables
Using ls in Scripts
Using ls in Scripts
ls
in scripts. It can break when filenames contain spaces, newlines, or other special characters. Use shell globbing, find
, or other more robust methods instead.Not Checking Command Exit Status
Not Checking Command Exit Status
set -e
option to exit on any error, or combine both approaches for more robust error handling.Using eval
Using eval
eval
whenever possible, especially with user input. It can lead to code injection vulnerabilities. If you must use it, validate input strictly and consider alternatives like case statements or function dispatching.Command Injection Vulnerabilities
Command Injection Vulnerabilities
--
to indicate the end of options when available, and consider using printf %q
to properly quote arguments for commands that don’t support --
.Using Backticks Instead of $()
Using Backticks Instead of $()
$()
for command substitution instead of backticks. It’s more readable, especially when nested, and more consistent with other shell constructs.Not Setting IFS When Reading Lines
Not Setting IFS When Reading Lines
IFS=
(empty) and use the -r
flag with read
to prevent backslash interpretation. This preserves leading and trailing whitespace and handles backslashes correctly.Using /bin/sh for Bash Scripts
Using /bin/sh for Bash Scripts
#!/bin/bash
as the shebang, not #!/bin/sh
. On many systems, /bin/sh
might be a different shell (like dash) that doesn’t support Bash features.Not Using set -u
Not Using set -u
set -u
(or set -o nounset
) to make your script exit when it tries to use an undefined variable. This helps catch typos and missing variables early.Not Using set -e
Not Using set -e
set -e
(or set -o errexit
) to make your script exit immediately if any command fails. This prevents the script from continuing in an unexpected state after an error.Not Using Shellcheck
Not Using Shellcheck
Using [ ] Instead of [[ ]]
Using [ ] Instead of [[ ]]
[[ ]]
instead of [ ]
for conditional tests in Bash. It’s more powerful, safer with empty variables, supports logical operators directly, and provides pattern matching.Hardcoding Paths
Hardcoding Paths
Not Using Functions
Not Using Functions
Using echo for Printing to stderr
Using echo for Printing to stderr
printf
instead of echo
for more consistent behavior across different systems, especially when printing to stderr or when dealing with strings that start with options like -n
or -e
.Using Uppercase Variable Names
Using Uppercase Variable Names
Not Using Local Variables in Functions
Not Using Local Variables in Functions
local
to declare function-specific variables. This prevents unintended side effects and makes functions more self-contained and reusable.Using Temporary Files Insecurely
Using Temporary Files Insecurely
mktemp
to create secure temporary files with unique names. Add a trap to clean up temporary files when the script exits, even if it exits due to an error.Not Using Double Brackets for Regex
Not Using Double Brackets for Regex
[[ ]]
with the =~
operator for regular expression matching. Single brackets [ ]
only support glob patterns, not regular expressions.Not Using Proper Shebang
Not Using Proper Shebang
#!/usr/bin/env bash
is more portable than #!/bin/bash
because it will find the Bash interpreter in the user’s PATH.Using Deprecated Syntax
Using Deprecated Syntax
$[...]
for arithmetic expansion. Use the modern equivalents like $((...))
instead.Not Using Parameter Expansion
Not Using Parameter Expansion