Skip to content

Reading a script before you run it

16 min

Make it show you first

Four ways to see what a line will do before it does it.

The shell will tell you what it is about to do, if you ask. **Put echo in front of it.** The line is expanded exactly as it would have been and then handed to echo instead of to rm, so you see the arguments the command would have received rather than the ones you think you wrote.

It is the cheapest audit there is, it works on any line, and it is the one to reach for when a path is built out of variables.

Try this

*Turn on the trace.* set -x prints each command to standard error after expansion, with a + in front. It shows you what actually ran rather than what was written, which is the same distinction the whole first track is about — and it stays out of the way, because it writes to stderr and never touches the output.

Try this

*Make an unset variable fatal.* set -u turns the empty-variable disaster into an error before it becomes a path: the expansion fails, the shell stops, and the command never runs. Not merely reported — everything after it does not happen, which is the whole of what the line is worth.

set -euo pipefail is the usual trio: stop on an error, stop on an unset variable, and let a failing stage of a pipeline count as a failure. It belongs at the top of anything you did not write yourself.

Try this

Nothing was removed and cleaned never printed. Without set -u that line empties the directory it was pointed at and reports success.

*Fetch it before you run it.* A pipe into sh cannot be read, cannot be diffed against last week's, and cannot be checked twice — the server is free to answer differently the second time. -o writes it to a file, and then it is just a file.

And when a line is doing something you cannot follow, hand it to the expansion trace: it shows the eight stages one at a time, and the answer is the engine's own rather than anybody's recollection.

Try this

$

Files

The files in the sandbox, with their modes, link counts and sizes
ModeLinksSizeName
drwxr-xr-x4project/
-rw-------166.env
-rw-r--r--143README.md
drwxr-xr-x2build/
-rw-r--r--16cache.tmp
-rw-r--r--19output.bin
-rw-r--r--195notes.txt
drwxr-xr-x2src/
-rw-r--r--129lib.sh
-rwxr-xr-x141main.sh