CMD Master
Back to Blog
UpdatedArnošt Havelka

How to Write a Safer Bash Backup Script with tar

Build a Bash backup script that validates its source, avoids silent overwrites, removes partial archives, and verifies the tar file.

Start Interactive Lesson
How to Write a Safer Bash Backup Script with tar

A useful Bash backup script should reject a missing source, keep the destination outside that source, avoid silently overwriting an earlier archive, remove partial output after failure, and inspect the archive before reporting success. The example below creates a compressed tar archive with those guardrails. It is a learning script, not a complete backup system. The Bash scripting lesson lets you practise how its parts fit together.

Start with explicit source and destination paths

Save this as backup.sh:

#!/usr/bin/env bash
set -euo pipefail

source_dir="${1:-$HOME/data}"
backup_dir="${2:-$HOME/backups}"

if [[ ! -d "$source_dir" ]]; then
  printf 'Source directory not found: %s\n' "$source_dir" >&2
  exit 1
fi

mkdir -p "$backup_dir"

source_parent=$(dirname "$source_dir")
source_name=$(basename "$source_dir")
timestamp=$(date '+%Y%m%d-%H%M%S')
archive="$backup_dir/${source_name}-${timestamp}.tar.gz"
partial="$archive.partial"

if [[ -e "$archive" || -e "$partial" ]]; then
  printf 'Backup destination already exists: %s\n' "$archive" >&2
  exit 1
fi

trap 'rm -f "$partial"' EXIT
tar -czf "$partial" -C "$source_parent" "$source_name"
tar -tzf "$partial" >/dev/null
mv "$partial" "$archive"
trap - EXIT

printf 'Backup created: %s\n' "$archive"

The first argument selects the source directory, and the second selects where archives are stored. Without arguments, the script uses $HOME/data and $HOME/backups. Keep the backup directory outside the source directory so the script does not try to archive its own output.

Understand the safety checks

set -euo pipefail makes this simple sequence stop on an unhandled command failure, an unset variable, or a failed command inside a pipeline. It is a guardrail, not a substitute for checking expected failure cases explicitly.

The directory test stops before tar when the source is missing. The timestamp prevents normal runs from reusing one fixed name, while the explicit existence check refuses an accidental same-second collision.

The script writes to a .partial path first. Its EXIT trap removes that partial file if tar, archive inspection, or another command fails. Only a successfully readable archive is moved to the final name, after which the trap is disabled.

Why tar uses -C

This command creates a gzip-compressed archive:

tar -czf "$partial" -C "$source_parent" "$source_name"

The options mean create (c), gzip-compress (z), and write to the following file (f). -C changes directory for the archive operation so it stores the source's directory name and contents rather than an absolute path.

Listing the archive checks that tar can read its structure:

tar -tzf "$archive"

That is useful verification, but it does not prove every file is current or that a restore will meet your needs.

Run and test the script

Check the syntax before the first run:

bash -n backup.sh
bash backup.sh "$HOME/data" "$HOME/backups"

Then perform a restore test in a temporary directory:

restore_dir=$(mktemp -d)
tar -xzf "$HOME/backups/data-YYYYMMDD-HHMMSS.tar.gz" -C "$restore_dir"
find "$restore_dir" -type f

Replace the example archive name with the one the script printed. Inspect representative restored files, then remove the temporary directory when you no longer need it.

What a real backup still needs

A local archive can be lost with the same disk as its source. A production backup plan also needs an independent destination, retention and deletion rules, monitoring, protected credentials, enough free space, and regular restore tests. Decide how concurrent file changes are handled as well; tar cannot create an application-consistent database backup by itself.

Review how to run a first Bash script if the shebang or permissions are unfamiliar, and use the tar lesson for focused archive practice. GNU documents archive creation, compression, overwrite behavior, and verification in the tar manual.

References

These documentation links provide authoritative details for the commands used in this article.

Up Next

Bash Orientation: CD Loop

Practice child and parent directory movement until path changes feel automatic.