Automations Anonymous
Sheet
Display
Read
Type

Sheet 04 · /automations/back-up-one-folder-every-night

Back up one folder every night and keep two weeks

A nightly cron job archives one folder to a dated tar.gz and deletes archives older than fourteen days, so a restore is always a single file away.

Difficulty:
beginner
Tools:
cron, bash, tar

Problem

Backups that depend on remembering to run them are not backups. The folder that matters is usually one folder, and copying it by hand lasts about a week before it stops happening.

Trigger

Cron, every night at 02:00 local time.

Prerequisites

  • 01A machine that is awake at the scheduled time. A laptop asleep at 02:00 skips the run.
  • 02Enough free space for fourteen compressed copies of the folder.
  • 03tar and cron, both present by default on macOS and Linux.

Steps

  1. 01

    Save the script as backup-folder.sh and make it executable bash

    chmod +x backup-folder.sh. Edit SOURCE and DEST at the top; nothing else needs changing.

  2. 02

    Run it once by hand and confirm the archive opens tar

    tar -tzf ~/Backups/Documents-YYYY-MM-DD.tar.gz lists the contents. If that fails, stop here and fix it before scheduling anything.

  3. 03

    Add the cron line cron

    crontab -e, then: 0 2 * * * $HOME/bin/backup-folder.sh >> $HOME/.backup.log 2>&1

  4. 04

    Check the log the next morning

    tail ~/.backup.log. One line per run, with the path it wrote.

Payload · sh

#!/usr/bin/env bash
# Nightly archive of one folder. Keeps the last 14 days, deletes the rest.
set -euo pipefail

SOURCE="$HOME/Documents"
DEST="$HOME/Backups"
KEEP_DAYS=14

mkdir -p "$DEST"
NAME="$(basename "$SOURCE")"
ARCHIVE="$DEST/$NAME-$(date +%Y-%m-%d).tar.gz"

tar --create --gzip --file "$ARCHIVE" --directory "$(dirname "$SOURCE")" "$NAME"
find "$DEST" -name "$NAME-*.tar.gz" -type f -mtime +"$KEEP_DAYS" -delete

echo "$(date +%Y-%m-%dT%H:%M:%S) wrote $ARCHIVE"

Failure modes

  • !The disk fills and tar writes a truncated archive. The script does not check free space, so watch the log and the archive sizes.
  • !The source folder is renamed or moved, tar exits non-zero, and set -e stops the run. Nothing is deleted, but nothing is backed up either.
  • !The archive sits on the same disk as the source, so one dead drive loses both. Point DEST at an external volume or a synced folder.
  • !cron runs with a minimal environment. Use absolute paths, and test the way cron will see it: env -i /bin/bash $HOME/bin/backup-folder.sh

JSON-LD · HowTo

{
  "@context": "https://schema.org",
  "@type": "HowTo",
  "name": "Back up one folder every night and keep two weeks",
  "description": "A nightly cron job archives one folder to a dated tar.gz and deletes archives older than fourteen days, so a restore is always a single file away.",
  "url": "https://automationsanonymous.com/automations/back-up-one-folder-every-night",
  "tool": [
    {
      "@type": "HowToTool",
      "name": "cron",
      "url": "https://automationsanonymous.com/tools/cron"
    },
    {
      "@type": "HowToTool",
      "name": "bash",
      "url": "https://automationsanonymous.com/tools/bash"
    },
    {
      "@type": "HowToTool",
      "name": "tar",
      "url": "https://automationsanonymous.com/tools/tar"
    }
  ],
  "step": [
    {
      "@type": "HowToStep",
      "position": 1,
      "name": "Save the script as backup-folder.sh and make it executable",
      "text": "chmod +x backup-folder.sh. Edit SOURCE and DEST at the top; nothing else needs changing.",
      "url": "https://automationsanonymous.com/tools/bash"
    },
    {
      "@type": "HowToStep",
      "position": 2,
      "name": "Run it once by hand and confirm the archive opens",
      "text": "tar -tzf ~/Backups/Documents-YYYY-MM-DD.tar.gz lists the contents. If that fails, stop here and fix it before scheduling anything.",
      "url": "https://automationsanonymous.com/tools/tar"
    },
    {
      "@type": "HowToStep",
      "position": 3,
      "name": "Add the cron line",
      "text": "crontab -e, then: 0 2 * * * $HOME/bin/backup-folder.sh >> $HOME/.backup.log 2>&1",
      "url": "https://automationsanonymous.com/tools/cron"
    },
    {
      "@type": "HowToStep",
      "position": 4,
      "name": "Check the log the next morning",
      "text": "tail ~/.backup.log. One line per run, with the path it wrote."
    }
  ],
  "datePublished": "2026-09-05T16:53:12.891Z"
}