thecodex.expert · The Codex Family of Knowledge
Tier 2 · Intermediate · Python Project

File Organizer

Automatically sort a messy folder into subfolders by file type. Your first real automation that changes your computer.

🧠 Teaches how to think spoonfed, every age Last verified:

1 The Problem

We want a script that looks at a messy folder (downloads, say) and sorts every file into a subfolder by its type — images together, documents together, and so on. It teaches working with the file system: listing, moving, and creating folders programmatically.

Where this shows up: backup scripts, deployment tools, media organisers, log rotation, any automation that manages files. This is the first project that does real work on your machine, not just in memory.

2 How to Think About It

Think about the sorting logic, before any code:

The plan — in plain English
1. List every file in the folder. → 2. For each file, look at its extension (.jpg, .pdf…) and decide its category. → 3. Make a subfolder for that category if it does not exist. → 4. Move the file in. Safe, repeatable, automatic.

List files in folder

For each file

Get its extension

Map extension to a category

Make category folder if needed

Move file into it

3 The Build — explained part by part

Here is the complete organizer. Each part is explained below.

Pythonorganize.py
from pathlib import Path
import shutil

# Map file extensions to category folder names.
CATEGORIES = {
    ".jpg": "Images", ".png": "Images", ".gif": "Images",
    ".pdf": "Documents", ".txt": "Documents", ".docx": "Documents",
    ".mp3": "Audio", ".wav": "Audio",
    ".zip": "Archives", ".tar": "Archives",
}

def organize(folder):
    folder = Path(folder)
    for item in folder.iterdir():
        if item.is_file():
            category = CATEGORIES.get(item.suffix.lower(), "Other")
            target = folder / category
            target.mkdir(exist_ok=True)     # make the folder if needed
            shutil.move(str(item), str(target / item.name))

if __name__ == "__main__":
    organize("./downloads")
    print("Done organizing.")
What each part does — in plain words
from pathlib import Path — the modern, safe way to work with files and folders. A Path object knows how to list, join, and inspect paths.

CATEGORIES — a lookup mapping each extension to a category folder. Data-driven, so adding a type is a one-line change.

folder.iterdir() — list everything in the folder. item.is_file() skips sub-folders so we only move files.

item.suffix.lower() — the file’s extension (like .jpg), lowercased so .JPG and .jpg match. CATEGORIES.get(..., "Other") looks it up, defaulting unknown types to “Other”.

target.mkdir(exist_ok=True) — create the category folder; exist_ok=True means “do not error if it already exists”.

shutil.move(...) — actually move the file into its category folder.
Common mistakes — and how to avoid them
✗ Running it on an important folder untested — moving files is hard to undo.
✓ Always test on a copy or practice folder first.
✗ Forgetting exist_ok=True — the second run crashes because the folder already exists.
✓ Use mkdir(exist_ok=True) so re-running is safe.
✗ Not lowercasing the extension — .JPG falls through to “Other”.
✓ Lowercase the suffix before looking it up.

4 Test & Prove Each Part

We test the categorising logic — which folder each extension maps to — without touching the real file system.

A .jpg maps to Images
A .pdf maps to Documents
An unknown extension maps to Other
Pythontest_organize.py
CATEGORIES = {
    ".jpg": "Images", ".png": "Images",
    ".pdf": "Documents", ".txt": "Documents",
    ".mp3": "Audio",
}


def categorise(extension):
    return CATEGORIES.get(extension.lower(), "Other")


def test_image():
    """.jpg goes to Images."""
    assert categorise(".jpg") == "Images"


def test_document():
    """.pdf goes to Documents."""
    assert categorise(".pdf") == "Documents"


def test_unknown():
    """An unknown type goes to Other."""
    assert categorise(".xyz") == "Other"

Run with pytest -v. We test the decision (which category) separately from the action (moving files), so tests are fast and safe — they never move real files. Separating decisions from side-effects is a key habit for file-system code.

5 The Interface

INPUTa folder paththe messy folder
What it expects
downloads/ containing:
  photo.jpg, report.pdf, song.mp3
OUTPUTorganised foldersfiles moved by type
What it returns
downloads/Images/photo.jpg
downloads/Documents/report.pdf
downloads/Audio/song.mp3

6 Run It & Automate It

Run it locally
python3 organize.py
Test on a copy first! Point it at a practice folder before a real one — it moves files for real.

Jenkins runs the tests automatically — each line explained below.

What you should see when it works
Terminala real run
Done organizing.
# downloads/ now contains Images/, Documents/, Audio/ subfolders with files sorted in
If it breaks — how to fix it
🚨 FileExistsError.
Add exist_ok=True to mkdir so existing folders are fine.
🚨 Files end up in “Other” unexpectedly.
Their extension is not in your map, or the case differs. Add it, and lowercase the suffix.
GroovyJenkinsfile
// Jenkinsfile — automated tests on every change.
pipeline {
    agent any
    stages {
        stage('Get the code') { steps { checkout scm } }       // download the code
        stage('Install') { steps { sh 'python3 -m venv venv && . venv/bin/activate && pip install pytest' } }  // test tool
        stage('Test') { steps { sh '. venv/bin/activate && pytest -v' } }   // run every test
    }
    post {
        success { echo 'All tests passed.' }
        failure { echo 'A test failed — look above.' }
    }
}
🎯 Try this next — make it yours
  1. Dry run mode. Print what would move without moving it. (Teaches: safe previews.)
  2. Undo log. Record every move so you can reverse it. (Teaches: logging actions.)
  3. By date. Sort into folders by month instead of type. (Teaches: file timestamps.)
What you learned
You learned to work with the file system using pathlib and shutil — listing, categorising, creating folders, and moving files. And you learned the safety habit of testing the decision logic apart from the destructive action. Related: pathlib, shutil.