- Difficulty:
- beginner
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
- 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.
- 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.
- 03
Add the cron line cron
crontab -e, then: 0 2 * * * $HOME/bin/backup-folder.sh >> $HOME/.backup.log 2>&1
- 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"
}