If your Downloads folder looks like a garage after a decade of neglect β PDFs next to MP4s, screenshots mixed with installer .exe files β this one's for you.
I wrote a Python script that watches my Downloads folder and auto-sorts everything into Documents/, Images/, Videos/, Archives/, and Code/ subfolders.
No external packages. No pip install. No bloated config files. Just Python's standard library.
The One-File Solution
#!/usr/bin/env python3
"""Downloads organizer β sorts files by type into categorized folders."""
import os
import shutil
from pathlib import Path
DOWNLOADS = Path.home() / "Downloads"
# Map file extensions to destination folders
RULES = {
"Documents": [
".pdf", ".doc", ".docx", ".txt", ".md", ".csv",
".xls", ".xlsx", ".ppt", ".pptx", ".odt",
],
"Images": [
".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg",
".webp", ".ico", ".tiff",
],
"Videos": [
".mp4", ".mov", ".avi", ".mkv", ".wmv", ".flv",
".webm",
],
"Audio": [
".mp3", ".wav", ".flac", ".aac", ".ogg", ".m4a",
],
"Archives": [
".zip", ".tar", ".gz", ".7z", ".rar", ".bz2",
],
"Code": [
".py", ".js", ".ts", ".html", ".css", ".json",
".xml", ".yaml", ".yml", ".sh", ".bat", ".sql",
".dockerfile", ".env",
],
"Installers": [
".exe", ".msi", ".dmg", ".deb", ".rpm", ".AppImage",
],
}
def organize():
if not DOWNLOADS.exists():
print(f"β Downloads folder not found: {DOWNLOADS}")
return
moved = 0
for item in DOWNLOADS.iterdir():
if item.is_dir():
continue # Skip existing folders
ext = item.suffix.lower()
destination = None
for folder, extensions in RULES.items():
if ext in extensions:
destination = DOWNLOADS / folder
break
if destination is None:
destination = DOWNLOADS / "Other"
destination.mkdir(exist_ok=True)
# Handle filename collisions
target = destination / item.name
if target.exists():
stem = item.stem
counter = 1
while target.exists():
target = destination / f"{stem}_{counter}{ext}"
counter += 1
shutil.move(str(item), str(target))
moved += 1
print(f" π¦ {item.name} β {folder if destination else 'Other'}")
print(f"\nβ
Done! Organized {moved} file(s).")
if __name__ == "__main__":
organize()
How It Works
-
Scan β Iterates through every file in
~/Downloads/ - Match β Checks the file extension against the rules dictionary
- Move β Creates the target folder if it doesn't exist, then moves the file
-
Collision handling β If a file with the same name already exists, appends
_1,_2, etc.
Run It
Save the script as organize_downloads.py and run:
python3 organize_downloads.py
Make it even easier β add it as a cron job to run every hour:
crontab -e
# Add this line:
0 * * * * /usr/bin/python3 /home/you/organize_downloads.py
Extending It
The RULES dictionary is easy to customize:
- Add new categories: Just add a new key with a list of extensions
- Change where files go: Modify the folder names
-
Add subfolder logic: Split
Code/intoCode/Python/,Code/JavaScript/etc.
Why This Matters
This is one of those "5-minute fix that saves you hours" scripts. It's also a great example of:
-
File I/O with
pathlib - String operations with file extensions
-
Error handling with
mkdir(exist_ok=True)and collision detection -
Standard library only β you don't always need
pip installto solve real problems
I use this script daily, alongside 12 other utility scripts in my toolkit. If you want the full collection (a web scraper, email engine, PDF generator, rate limiter, and more), check out the Python Scripts Collection β 13 ready-to-run scripts with zero external dependencies.
Happy organizing!
Top comments (0)