The Downloads Folder Problem

Open your Downloads folder. Screenshots from last week, PDFs from three months ago, installers, zip files, random images, a .deb package you don't remember downloading. It's chaos.

Manually sorting files is boring and nobody does it. But a Python script will do it in 0.2 seconds, every time.

By the end of this guide, you'll have a script that turns this:

Downloads/
├── IMG_4529.png
├── tax-return-2025.pdf
├── ubuntu-26.04.iso
├── movie-night.mp4
├── resume-final-v2.docx
├── song.mp3
└── random-meme.gif

Into this:

Downloads/
├── Images/
│   ├── IMG_4529.png
│   └── random-meme.gif
├── Documents/
│   ├── tax-return-2025.pdf
│   └── resume-final-v2.docx
├── Videos/
│   └── movie-night.mp4
├── Music/
│   └── song.mp3
└── Archives/
    └── ubuntu-26.04.iso

The Full Script (Then We'll Explain Every Line)

#!/usr/bin/env python3
"""Organize files in a folder by their extension."""

import os
import shutil
from pathlib import Path

# ── Config ──
FOLDER_TO_ORGANIZE = Path.home() / "Downloads"  # Change this if needed

# Map extensions to folder names
CATEGORIES = {
    # Images
    ".jpg": "Images", ".jpeg": "Images", ".png": "Images",
    ".gif": "Images", ".webp": "Images", ".svg": "Images",
    ".bmp": "Images", ".ico": "Images",
    # Documents
    ".pdf": "Documents", ".docx": "Documents", ".doc": "Documents",
    ".txt": "Documents", ".md": "Documents", ".csv": "Documents",
    ".xlsx": "Documents", ".pptx": "Documents", ".odt": "Documents",
    # Videos
    ".mp4": "Videos", ".mov": "Videos", ".avi": "Videos",
    ".mkv": "Videos", ".webm": "Videos",
    # Music
    ".mp3": "Music", ".wav": "Music", ".flac": "Music",
    ".aac": "Music", ".ogg": "Music",
    # Archives & installers
    ".zip": "Archives", ".tar.gz": "Archives", ".gz": "Archives",
    ".rar": "Archives", ".7z": "Archives", ".deb": "Archives",
    ".iso": "Archives", ".AppImage": "Archives",
    # Code
    ".py": "Code", ".js": "Code", ".html": "Code",
    ".css": "Code", ".json": "Code", ".sh": "Code",
}


def organize(folder: Path):
    """Move files in `folder` into categorized subfolders."""
    moved = 0
    skipped = 0

    for item in folder.iterdir():
        # Skip directories, hidden files, and this script itself
        if item.is_dir():
            continue
        if item.name.startswith("."):
            continue

        # Get the file extension (lowercase for matching)
        ext = item.suffix.lower()
        # Handle double extensions like .tar.gz
        if item.name.endswith(".tar.gz"):
            ext = ".tar.gz"

        # Find the right category
        category = CATEGORIES.get(ext)

        if category is None:
            print(f"  ⏭  Skipped (unknown type): {item.name}")
            skipped += 1
            continue

        # Create the category folder if it doesn't exist
        dest_dir = folder / category
        dest_dir.mkdir(exist_ok=True)

        # Handle duplicate file names
        dest = dest_dir / item.name
        if dest.exists():
            # Append a number instead of overwriting
            stem = item.stem
            counter = 1
            while dest.exists():
                dest = dest_dir / f"{stem}_{counter}{ext}"
                counter += 1

        # Move the file
        shutil.move(str(item), str(dest))
        print(f"  ✓ {item.name} → {category}/")
        moved += 1

    print(f"\nDone! Moved {moved} files, skipped {skipped}.")


if __name__ == "__main__":
    print(f"Organizing: {FOLDER_TO_ORGANIZE}")
    organize(FOLDER_TO_ORGANIZE)

How It Works

1. Finding Your Downloads Folder

FOLDER_TO_ORGANIZE = Path.home() / "Downloads"

Path.home() returns your home directory — /home/alice on Linux, C:\Users\alice on Windows, /Users/alice on Mac. Then we append Downloads. This works cross-platform without any if statements.

2. The Extension-to-Category Map

CATEGORIES = {
    ".jpg": "Images", ".png": "Images", ".gif": "Images",
    ".pdf": "Documents", ".docx": "Documents",
    ...
}

A dictionary that maps every file extension to a folder name. To add your own types, just add entries. Want Photoshop files to go to "Design"? Add ".psd": "Design".

3. Iterating Through Files

for item in folder.iterdir():
    if item.is_dir():
        continue            # Skip folders
    if item.name.startswith("."):
        continue            # Skip hidden files

iterdir() goes through every file in the folder one by one. We skip directories (we only organize files) and hidden files (files starting with . like .bashrc).

4. Getting the Extension

ext = item.suffix.lower()
if item.name.endswith(".tar.gz"):
    ext = ".tar.gz"

suffix returns the extension (.JPG.jpg after lower()). The .tar.gz case is special — suffix only returns .gz, so we check for the full .tar.gz ending.

5. Handling Duplicates

if dest.exists():
    counter = 1
    while dest.exists():
        dest = dest_dir / f"{stem}_{counter}{ext}"
        counter += 1

If you download report.pdf twice, the second one becomes report_1.pdf instead of overwriting the first. The while loop keeps incrementing the counter until it finds an unused name.

Customizing the Script

Change the folder

# Organize a specific folder instead of Downloads
FOLDER_TO_ORGANIZE = Path("/home/alice/Desktop/Stuff")

Add your own file types

# Add these to the CATEGORIES dict:
".epub": "Books",
".mobi": "Books",
".psd": "Design",
".xd": "Design",

Run on a schedule (Linux cron)

# Run every hour
0 * * * * python3 /home/alice/scripts/organize_downloads.py

If you're new to cron, our Linux Terminal Basics guide includes cron fundamentals. For a complete backup solution using the same idea, see our Python Automated Backups guide.

What to Do Next

Once this script works for you, try these variations:

  1. Add a dry-run mode — print what would move without actually moving anything
  2. Organize by date — move files into 2026-08/, 2026-07/, etc. instead of by type
  3. Log to a file — keep a record of every move for when you can't find something
  4. Watch mode — use watchdog library to automatically organize new files as they're downloaded

For another practical Python automation project, check out our File Renaming guide — a 10-line script that renames hundreds of files in seconds.

The best part about this script? You write it once and it works forever. I've been running mine for months. My Downloads folder has never been cleaner — and I haven't manually sorted a single file.