Python Central HubSign in

Automation and Scripting / Phase 1: OS & File System Automation

Automating File Backups

Create simple backup scripts using pathlib and zip archives.

Backup strategy (simple and effective)

  • choose what to back up
  • create timestamped archives
  • store backups in a separate location

Zip a folder

Python
from __future__ import annotations
 
from datetime import datetime
from pathlib import Path
import shutil
 
 
def backup_folder(folder: Path, out_dir: Path) -> Path:
    folder = folder.resolve()
    out_dir.mkdir(parents=True, exist_ok=True)
 
    stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    archive_base = out_dir / f"{folder.name}_{stamp}"
 
    # creates archive_base.zip
    archive_path = shutil.make_archive(str(archive_base), "zip", root_dir=str(folder))
    return Path(archive_path)
 
 
p = backup_folder(Path("./demo"), Path("./backups"))
print("created", p)

How the script works

shutil.make_archive is the standard-library shortcut for building a zip (or tar) file. It takes the base name of the archive without the extension, the format, and the folder to pack. It returns the full path of the file it created, which is why the function returns a Path.

A few decisions in the script matter:

  • folder.resolve() turns ./demo into an absolute path, so folder.name is a real name even if you pass ..
  • The timestamp (20260929_143005) makes every archive name unique and sorts in date order. You never overwrite yesterday's backup by accident.
  • out_dir.mkdir(parents=True, exist_ok=True) creates the backup folder on the first run and does nothing on later runs. That makes the script safe to run twice.
  • root_dir makes the paths inside the zip relative to the folder, so the archive does not contain your whole drive layout.

Keeping only the newest backups

A backup script that never cleans up will eventually fill the disk. This function keeps the newest keep archives and deletes the rest. Try it with dry_run=True first.

Python
from pathlib import Path
 
 
def prune_backups(out_dir: Path, prefix: str, keep: int = 5, dry_run: bool = True):
    archives = sorted(out_dir.glob(f"{prefix}_*.zip"))  # timestamp names sort oldest first
    old = archives[:-keep] if keep > 0 else archives
    for path in old:
        if dry_run:
            print("would delete", path)
        else:
            path.unlink()
            print("deleted", path)
 
 
prune_backups(Path("./backups"), "demo", keep=5)

Sorting by name works only because the timestamp is in year-month-day order. If you change the format to %d-%m-%Y, the sort breaks.

Common mistakes

  • Backing up into the folder you are archiving. The archive then contains the previous archives and grows each run. Keep out_dir outside folder.
  • Never testing a restore. A backup you have not opened is only a hope. Unzip one now and then and check the files.
  • Keeping backups on the same disk. If the disk fails, both copies go. Copy the archive to another drive or a cloud folder as well.
  • Using the local clock without thinking. datetime.now() is local time. That is fine for names, but two runs during a daylight-saving change can sort oddly.

Adapting it

Change "zip" to "gztar" for a smaller .tar.gz. Add a list of folders and loop over it. Schedule the script with cron or Task Scheduler (Phase 6) so it runs every night without you.

Tips

  • keep multiple backups
  • test restore occasionally
  • don’t back up into the same folder you’re archiving

Visualize it

A backup script moves files from the source folder to a safe destination in a few clear steps.

diagram File backup flow mermaid
How a backup script moves files from source to destination

πŸ§ͺ Try It Yourself

Exercise 1 – List Files with os.listdir

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 2 – Join Paths with os.path.join

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Exercise 3 – Write and Read a File

exerciseYour turn

Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.

Output
Press Run to see what your code prints.

Was this page helpful?

Let us know how we did