DEV Community

Cover image for The Simplest Automated Backup That Actually Works (6 Lines of Bash)
Anguishe
Anguishe

Posted on • Originally published at bashsnippets.xyz

The Simplest Automated Backup That Actually Works (6 Lines of Bash)

I have lost work exactly once.

It was a side project. A static site I'd been building over a weekend. I was reorganizing the folder structure, running mv commands to shuffle things around, and I fat-fingered a path. Moved an entire directory into a subdirectory of itself. The folder structure collapsed like a house of cards. Some files survived. Some didn't. The ones that didn't were the ones I cared about.

I spent the rest of that Sunday recreating work I'd already done. Not because of a server crash. Not because of a disk failure. Because I moved a folder wrong and didn't have a copy.

The thing is, making a copy takes 6 lines of bash.


The Script

#!/bin/bash
# Automated File Backup
# Copies a folder to /backup with today's timestamp.
# Run manually or schedule with cron — works either way.

SOURCE="/home/user/documents"   # ← change this to your folder
DEST="/backup"                   # ← change this to your backup location
DATE=$(date +%Y-%m-%d_%H-%M)

mkdir -p "$DEST"
cp -r "$SOURCE" "$DEST/backup_$DATE"
echo "✓ Done. Saved to: $DEST/backup_$DATE"
Enter fullscreen mode Exit fullscreen mode

That's it. cp -r copies everything recursively. date stamps it. mkdir -p creates the destination if it doesn't exist. You get a folder called backup_2026-05-22_14-30 with an exact snapshot of whatever you pointed it at.


What Makes This Work

SOURCE is the folder you want backed up. Could be your project directory, your web server files, your config folder — anything you'd be upset to lose.

DEST is where backups land. A different drive is ideal. An external mount is better. Even a different folder on the same disk is better than nothing.

DATE=$(date +%Y-%m-%d_%H-%M) creates a timestamp string like 2026-05-22_14-30. Every backup gets its own folder, and they sort chronologically because the format starts with the year. This isn't a small detail — if you use MM-DD-YYYY, your backups sort by month instead of by date, which is useless when you're trying to find last Tuesday's copy.

mkdir -p is the flag that means "create this directory, and if it already exists, don't complain." Without -p, the second time you run the script, mkdir throws an error because the folder already exists.

cp -r means "copy recursively" — every file, every subdirectory, everything inside the source. Without -r, cp only copies individual files and skips directories entirely.


The Only Way This Makes Sense: Automate It

Running this manually every day is a chore you'll forget by Wednesday. The entire point is to schedule it once and never think about it again.

crontab -e
Enter fullscreen mode Exit fullscreen mode

Add:

0 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1
Enter fullscreen mode Exit fullscreen mode

That runs the backup every night at 2 AM and logs the output. The 2>&1 catches any error messages too, so if the backup fails, you'll see why in the log instead of finding out three weeks later when you actually need the backup.

If you've never set up a cron job before (or if you get the syntax wrong every time like I used to), I have a free cron job builder that generates the line for you visually.


The Gotcha Nobody Warns You About

This script creates a new timestamped folder every time it runs. Run it daily for a year and you've got 365 backup folders. That adds up.

Add this line before the final echo:

find "$DEST" -name "backup_*" -mtime +30 -type d -exec rm -rf {} +
Enter fullscreen mode Exit fullscreen mode

That deletes any backup folder older than 30 days. Adjust the number based on how much disk space you have and how far back you'd realistically need to restore.

If you want a more robust version of this with compression and configurable retention, the MySQL Database Backup script uses the same pattern with gzip and find -delete.


Variations I Actually Use

Back up to an external drive:

DEST="/mnt/external-drive/backups"
Enter fullscreen mode Exit fullscreen mode

Just make sure the drive is mounted before the script runs. If it's not, mkdir -p creates the path on your main drive instead, which defeats the purpose.

Back up a web server's files:

SOURCE="/var/www/html"
DEST="/backup/www"
Enter fullscreen mode Exit fullscreen mode

Pair this with the MySQL backup script and you've got both your files and your database covered.

Add a size check after the backup:

SIZE=$(du -sh "$DEST/backup_$DATE" | cut -f1)
echo "✓ Backup size: $SIZE"
Enter fullscreen mode Exit fullscreen mode

Useful for catching the moment your project suddenly doubles in size because someone committed a 2GB video file.


Full script, line-by-line walkthrough, cron setup, and more variations:

bashsnippets.xyz/snippets/automated-file-backup.html

markdown---
title: I Alias This One-Liner to 'mktoday' and Use It Every Single Week
published: true
description: One bash command that creates a folder stamped with today's date. Add it as an alias and never lose track of project folders again. Takes 30 seconds to set up.
tags: bash, linux, productivity, beginners
canonical_url: https://bashsnippets.xyz/snippets/create-dated-folder.html

cover_image: https://bashsnippets.xyz/og-image.png

My project folder used to look like this:
new-site/
new-site-2/
new-site-final/
new-site-final-ACTUAL/
test-backup/
backup-old/

Yours probably looks similar. We've all been there. You start a project, name the folder something reasonable, and then six months later there are four variations of it and you have no idea which one is current.

The fix is embarrassingly simple: put the date in the folder name when you create it.


The Command

mkdir "$(date +%Y-%m-%d)_project-name"
Enter fullscreen mode Exit fullscreen mode

That creates: 2026-05-22_project-name

That's it. One command. But the trick is making it effortless enough that you actually use it every time.


Make It an Alias

Open your .bashrc (or .zshrc if you're on macOS/zsh):

nano ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

Add this line at the bottom:

alias mktoday='mkdir "$(date +%Y-%m-%d)_${1:-project}"'
Enter fullscreen mode Exit fullscreen mode

Save, then reload:

source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

Now you can type:

mktoday client-redesign
Enter fullscreen mode Exit fullscreen mode

And get: 2026-05-22_client-redesign

No thinking. No formatting. No "was it DD-MM or MM-DD?" The alias handles it.


Why YYYY-MM-DD and Not Anything Else

This isn't a style preference. It's a sorting issue.

If you use MM-DD-YYYY (the American date format), your folders sort like this:
01-15-2026_project/
02-03-2025_project/
03-22-2026_project/
12-01-2024_project/

That's sorted by month, not by date. January 2026 comes before February 2025. Useless.

With YYYY-MM-DD (ISO 8601), they sort correctly:
2024-12-01_project/
2025-02-03_project/
2026-01-15_project/
2026-03-22_project/

Chronological order. In every file manager. In every ls output. On every operating system. This is why ISO 8601 exists.


The Script Version (With Backup Built In)

If you want the folder creation to also copy files into it — like a timestamped backup — here's the expanded version:

#!/bin/bash
SOURCE="/home/user/documents"
BACKUP_ROOT="/backup"
DATE=$(date +%Y-%m-%d_%H-%M)
DEST="$BACKUP_ROOT/$DATE"

mkdir -p "$DEST"
cp -r "$SOURCE" "$DEST"
echo "✓ Backed up to: $DEST"
Enter fullscreen mode Exit fullscreen mode

This is the same concept but applied to automation. Create a dated folder, copy files into it, done. Schedule it with cron and you've got timestamped versioned backups.


The date Format Codes You'll Actually Use

You don't need to memorize all of them. Here are the ones that matter:

%Y — 4-digit year (2026)
%m — 2-digit month (05)
%d — 2-digit day (22)
%H — Hour in 24h format (14)
%M — Minutes (30)
%b — Abbreviated month name (May)

So date +%Y-%m-%d gives you 2026-05-22 and date +%Y-%m-%d_%H-%M gives you 2026-05-22_14-30 if you need time precision too.


Common Mistakes

Forgetting quotes around the folder name. If your project name has spaces, mkdir $(date +%Y-%m-%d)_my project creates two things: a folder called 2026-05-22_my and whatever bash makes of the word project on its own. Always wrap it: mkdir "$(date +%Y-%m-%d)_my project".

The alias not surviving a reboot. Adding alias mktoday=... in the terminal works for that session only. You have to put it in ~/.bashrc AND run source ~/.bashrc for it to stick.


This is one of those things that takes 30 seconds to set up and quietly makes your life better every week. Full walkthrough, more format examples, and the backup version:

bashsnippets.xyz/snippets/create-dated-folder.html

Top comments (0)