Bash scripting pitfalls and solutions – how to do (safe) things in bash
- Published at
- Updated at
- Reading time
- 3min
If you ever tried to write a good-looking but also well functioning and safe shell script, you know that this is not a trivial task. Unfortunately, most of the shells out there (and bash is no exception) make it hard to do things the right way. Or rephrased in plain English – most shells make it easy to do the wrong things.
People coming from languages like JavaScript have to worry about the unfamiliar syntax and the fact that things like conditions, loops, and other straightforward principles become a journey of copying snippets from Stack Overflow.
Suppose you're like me and want to get into shell scripting, do yourself one favor first. Please have a look at ShellCheck. Someone recommended me this tool last year at a hackathon, and it's golden. ShellCheck is an online tool (but can also come as an editor extension) that analyzes your shell scripts and tells you what's wrong. The tool gives you many resources and possible improvements. By looking at ShellCheck and implementing its advice, your scripts get at least one level better, if not two!
Today, I came across Bash pitfalls. It's an incredible useful bag of 59 common bash mistakes and how to do better. This page is one for the bookmarks! Let me share my "favorites".
Rule number one when writing shell scripts – quote your variables. After using ShellCheck for several months now, I can say that I rarely make this particular mistake anymore.
Variables without quotes can behave differently than you might expect.
Let me show you only one example where missing quotes bite you.
headline="* Headline *"
echo $headline # "dir1 dir2 dir3 Headline dir1 dir2 dir3"
# ☝️ echos everything matching the "*" glob pattern
echo "$headline" # "* Headline *"
# ☝️ works as expected
Variables that include spaces or globbing patterns can result in unexpected expansion.
This behavior not only applies to echo
. Have a look at the following copy command without variable quotes: cp $file $target
. If $file
or $target
include certain characters, it will break and go south, too.
Rule number one, forever and ever – use quotes when dealing with variables in bash.
I wasn't aware of the next behavior on this list. What happens if a variable includes -n
and you want to echo it out?
$ var="-n hello world"
$ echo $var
hello world$ # whoops?! What's this?
echo
considers options in variables. 😲 The included -n
option leads to the command not printing a trailing newline character. The safe way to print is to use printf
.
var="-n hello world"
printf "%s\n" "$var" # print a passed-in string followed by \n
Using printf
, you can strictly define how variables should be printed by defining placeholders (%s
is a string placeholder). Go for printf
to avoid surprises.
If you're navigating the file system in your shell command using cd
, you should make sure the navigations succeeded before moving on. For example, if you're planning to remove some caching files, you want to be sure that you're in the correct directory before running anything related to file removal.
The safe way to approach navigations is to always check for success:
# run a single command only after successful navigation
cd /some-dir && some-command
# run multiple commands after navigation
# exit if the navigation was not successful
cd /some-dir || exit 1
some-command
another-command
And these are only three tips when writing bash scripts. Read all the 59 Bash Pitfalls online and improve your bash scripts. ✌️
Join 5.5k readers and learn something new every week with Web Weekly.