Skip to content
Laviyx Learn

Try

Python course menu

Automate Boring Tasks With Python: Files, Folders, CSV Reports and Backups

Practical Python automation for beginners: organise a messy downloads folder by file type, batch rename files, turn CSV data into a summary report, zip backups, scan log files, and schedule scripts to run automatically.

Intermediate8 min readUpdated
On this page

One of the best reasons to learn Python is to make the computer do repetitive work for you. Tasks that take an hour of clicking (sorting files, renaming photos, building weekly reports) can become a script that runs in seconds. This lesson builds several small, real automations using only the standard library.

1. Organise a downloads folder by file type#

Python
from pathlib import Path

folder = Path("downloads")

categories = {
    "Documents": {".pdf", ".txt", ".csv"},
    "Images": {".jpg", ".png"},
    "Music": {".mp3"},
}

for file in folder.iterdir():
    if not file.is_file():
        continue
    ext = file.suffix.lower()                       # ".PDF" -> ".pdf"
    target = next((cat for cat, exts in categories.items() if ext in exts), "Other")
    (folder / target).mkdir(exist_ok=True)
    file.rename(folder / target / file.name)

for sub in sorted(folder.iterdir()):
    print(sub.name, sorted(f.name for f in sub.iterdir()))

Starting with report.pdf, photo.jpg, notes.txt, song.mp3, scan.PDF, data.csv and logo.png in the folder:

Output
Documents ['data.csv', 'notes.txt', 'report.pdf', 'scan.PDF']
Images ['logo.png', 'photo.jpg']
Music ['song.mp3']

Key ideas:

  • Path.iterdir() lists everything in a folder; is_file() skips sub-folders.
  • file.suffix.lower() normalises extensions so .PDF and .pdf are treated the same.
  • next(..., "Other") finds the first matching category, with a fallback.
  • rename() moves the file.

2. Batch rename files#

Rename camera photos to something meaningful, with numbered, zero-padded names:

Python
from pathlib import Path

folder = Path("photos")
for i, file in enumerate(sorted(folder.glob("*.jpg")), start=1):
    new_name = f"goa-trip-{i:02d}{file.suffix}"
    print(f"{file.name} -> {new_name}")
    file.rename(file.with_name(new_name))

print(sorted(p.name for p in folder.iterdir()))
Output
IMG_0001.jpg -> goa-trip-01.jpg
IMG_0002.jpg -> goa-trip-02.jpg
IMG_0003.jpg -> goa-trip-03.jpg
['goa-trip-01.jpg', 'goa-trip-02.jpg', 'goa-trip-03.jpg']

{i:02d} pads numbers to two digits so files sort correctly (02 before 10). A safe habit is a dry run: comment out the rename line, check the printed plan, then run it for real.

3. Turn raw CSV data into a summary report#

Given sales.csv:

sales.csv (Text)
date,region,amount
2026-10-01,North,1200
2026-10-01,South,800
2026-10-02,North,950
2026-10-02,South,1300
2026-10-03,North,700
Python
import csv
from pathlib import Path

totals = {}
with open("sales.csv", newline="", encoding="utf-8") as f:
    for row in csv.DictReader(f):
        totals[row["region"]] = totals.get(row["region"], 0) + int(row["amount"])

with open("summary.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["region", "total"])
    for region, total in sorted(totals.items()):
        writer.writerow([region, total])

print(Path("summary.csv").read_text(encoding="utf-8"))
Output
region,total
North,2850
South,2100

The output CSV opens directly in Excel or Google Sheets. For bigger data work, the pandas library does this in one line, but the standard library is enough for many everyday reports.

4. Zip a dated backup#

Python
import shutil
from datetime import date

archive = shutil.make_archive(f"backup-{date.today()}", "zip", "backup-source")

shutil.make_archive zips a whole folder. With today's date of 23 October 2026, it creates backup-2026-10-23.zip. The shutil module also copies (copy2, copytree) and moves (move) files and folders.

5. Scan log files for errors#

Python
from pathlib import Path

counts = {}
for log in sorted(Path("logs").glob("*.log")):
    errors = sum(1 for line in log.read_text().splitlines() if line.startswith("ERROR"))
    counts[log.name] = errors

print(counts, sum(counts.values()))
Output
{'app-1.log': 1, 'app-2.log': 2} 3

glob("*.log") picks only log files (a readme.txt in the same folder is ignored). Use rglob to search sub-folders too, and regular expressions for more complex patterns.

Running scripts automatically#

Once a script works, let the computer run it on a schedule:

SystemToolExample
WindowsTask Schedulercreate a task that runs python C:\scripts\organise.py daily
macOS / Linuxcron0 9 * * 1 /usr/bin/python3 /home/asha/scripts/report.py (every Monday at 9:00)

For scripts that wait between checks, time.sleep(seconds) pauses the program.

Ideas for your own automations#

  • Rename invoices using the date and client name found inside them.
  • Send yourself an email summary of a spreadsheet each morning (smtplib).
  • Resize every image in a folder (Pillow library).
  • Fill in Excel templates (openpyxl library).
  • Download data from an API and save a daily CSV.

Common mistakes#

Practice#

Practice exercise

Write a script that lists every .txt file in a folder (including sub-folders) together with its size in bytes, largest first.

Show hint

Path(folder).rglob("*.txt") finds the files; f.stat().st_size gives the size. Collect (size, name) pairs and sort them in reverse.

Show solution
Python
from pathlib import Path

def txt_sizes(folder):
    files = [(f.stat().st_size, str(f)) for f in Path(folder).rglob("*.txt")]
    for size, name in sorted(files, reverse=True):
        print(f"{size:>8} bytes  {name}")

txt_sizes(".")

The output depends on your files, for example:

Output
    1500 bytes  notes/big.txt
      42 bytes  todo.txt

{size:>8} right-aligns the numbers so the column is easy to read.

Key takeaway#

Finished this lesson?