Debugging Bash Scripts - Part 3 - Using echo

Here is the list of all the Bash debugging posts:

This debugging tool is useful in your Bash scripts and also in any Bash one-liners that you write.

The echo tool will print any input you give it. Most importantly, it will not execute any commands that are included in the input you give it but it will expand variables, wildcards, etc to show you everything that would happen when you run that command.

The following Bash script will create 5 directories in a for loop:

#!/bin/bash

for i in {1..5}; do
    mkdir "$i"
done

Or as a one-liner:

for i in {1..5}; do mkdir "$i"; done

Both the script and the one-liner will execute silently by default and create the 5 directories. If you are making significant changes to or including rm in your script then it is always useful to see exactly what the script will do before you run it.

Simply insert echo before the command (mkdir) and echo will print everything that will happen, e.g.:

#!/bin/bash

for i in {1..5}; do
    echo mkdir "$i"
done

Or

for i in {1..5}; do echo mkdir "$i"; done

These now do the following:

$ for i in {1..5}; do echo mkdir $i; done
mkdir 1
mkdir 2
mkdir 3
mkdir 4
mkdir 5

Crucially, the mkdir is not executed, and no changes are made to your system, but you can see every command that would have been executed.

This becomes a very healthy sanity check in case you make a typo or populate a variable with something problematic.

Take, for example, the following script (DO NOT RUN THIS SCRIPT!!!):

#!/bin/bash

DIRS="/ working/tmp"

rm -rf "$DIRS"

If you run this script as root the space in the variable, "/ working/tmp" will delete your entire filesystem.

This is because Bash will parse the space as indicating two directories to delete recursively and run the following two commands rm -rf / and rm -rf working/tmp. Executing rm -rf / will start at the root of your filesystem and proceed to delete everything.

It’s obvious in this short scrip but can be much less obvious in a long script especially where variables are populated from the system or another script.

Changing this script, on a test run, to:

#!/bin/bash

DIRS="/ working/tmp"

echo rm -rf "$DIRS"

Will quickly let you know exactly which directories will get deleted without actually deleting anything.