Shell Scripting Cookbook

Tips I have learned on how to do things in shell scripts.

Quit or Exit the Script if a Failure Occurs

Set the shell's e option.

#!/bin/sh
set -e
true
false

Alternative way to set the e option.

#!/bin/sh -e
true
false

To disable the option use +.

#!/bin/sh
set -e
true
set +e
false

Compare Version Numbers

Comparing two version numbers in dot separated format (e.g. 1.2.3) can be done in two ways.

Using BSD or GNU sort to find older version.

#!/bin/sh
a=1.2.0
b=1.2.1
printf "${a}\n${b}\n" | sort -t. -k 1,1n -k 2,2n -k 3,3n | head -n1

Using BSD or GNU sort to find newer version.

#!/bin/sh
a=1.2.0
b=1.2.1
printf "${a}\n${b}\n" | sort -t. -k 1,1nr -k 2,2nr -k 3,3nr | head -n1

Using GNU sort to find older version.

#!/bin/sh
a=1.2.0
b=1.2.1
printf "${a}\n${b}\n" | sort -V | head -n1

Using GNU sort to find newer version.

#!/bin/sh
a=1.2.0
b=1.2.1
printf "${a}\n${b}\n" | sort -Vr | head -n1

Assert

The test command is a rough equivalent to assert in other languages. Read its man page (man test) for more information.

Recover from Error Return Code

For commands that can return a non-zero exit code and possibly stop the script, use OR (||) operator with an alternative command that is sure to succeed. The true boolean value is one such command.

#!/bin/sh -e
git clone https://example.com/example.git /path/already/exists || true

Another example is to create and checkout a git branch that already exists.

#!/bin/sh -e
git checkout -b mybranch origin/mybranch || git checkout mybranch

The shell builtin : (used without arguments here) returns a zero exit code. In this case true and : are functionally equivalent.

#!/bin/sh -e
git clone https://example.com/example.git /path/already/exists || :

Source a File

To source a file means to execute it as if it was entered by a user manually. It is not run in a separate shell. So e.g. any export-ed variables become available in the current script as environment variables.

In Bourne shell (/bin/sh) command . is used to source a file. Command source does not work in /bin/sh.

#!/bin/sh
. file_to_source.sh