A messy Downloads folder is a perfect first Python automation project. The script in this guide sorts files into Images, Documents, Videos, Audio, Archives, and Other folders. More importantly, it includes two protections that many beginner examples miss: a dry-run mode that previews every move and automatic renaming when a file already exists.
You do not need to install a package. The solution uses Python’s standard library and works on Windows, macOS, and Linux. Run it on a small test folder first. When the preview looks correct, change one setting to perform the moves.
What the Python file organizer does
- Finds files directly inside your Downloads folder.
- Reads each file’s extension in lowercase.
- Maps common extensions to useful category folders.
- Leaves existing subfolders alone.
- Previews every planned move before changing anything.
- Renames duplicates instead of overwriting them.
The script uses Python’s pathlib module to work with paths and files. It uses shutil.move to move a file only after you disable dry-run mode.
The complete safe Downloads organizer script
Save this code as organize_downloads.py in Documents or another folder outside Downloads.
from pathlib import Path
from shutil import move
SOURCE = Path.home() / "Downloads"
DRY_RUN = True
RULES = {
"Images": {".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"},
"Documents": {".pdf", ".doc", ".docx", ".txt", ".csv", ".xls", ".xlsx"},
"Videos": {".mp4", ".mov", ".mkv", ".avi", ".webm"},
"Audio": {".mp3", ".wav", ".m4a", ".flac", ".aac"},
"Archives": {".zip", ".rar", ".7z", ".tar", ".gz"},
}
def category_for(file_path):
extension = file_path.suffix.lower()
for category, extensions in RULES.items():
if extension in extensions:
return category
return "Other"
def unique_destination(file_path, destination_folder):
candidate = destination_folder / file_path.name
counter = 1
while candidate.exists():
candidate = destination_folder / (
f"{file_path.stem}-{counter}{file_path.suffix}"
)
counter += 1
return candidate
def organize():
if not SOURCE.exists():
raise FileNotFoundError(f"Folder not found: {SOURCE}")
script_file = Path(__file__).resolve()
for item in SOURCE.iterdir():
if not item.is_file() or item.resolve() == script_file:
continue
category = category_for(item)
destination_folder = SOURCE / category
destination = unique_destination(item, destination_folder)
action = "WOULD MOVE" if DRY_RUN else "MOVING"
print(f"{action}: {item.name} -> {category}/{destination.name}")
if not DRY_RUN:
destination_folder.mkdir(exist_ok=True)
move(str(item), str(destination))
if __name__ == "__main__":
organize()
Understand the four most important parts
1. Path.home finds your user folder
Path.home() / "Downloads" builds the usual Downloads location without hard-coding a Windows username or a macOS home path. If your Downloads folder is stored elsewhere, replace SOURCE with the full path to your chosen folder. Use a raw string for a Windows path, such as Path(r"D:\My Downloads").
2. suffix.lower normalises file extensions
A file can be named PHOTO.JPG or photo.jpg. Converting the suffix to lowercase lets both names match the same .jpg rule. Files without a recognised suffix safely fall into Other instead of stopping the program.
3. iterdir scans only one level
SOURCE.iterdir() reads the items directly inside the selected folder. The is_file() check skips directories, so the organizer does not enter an existing project folder and rearrange its contents. This limited scope is deliberate: non-recursive automation is easier for a beginner to inspect and reverse.
4. unique_destination protects existing names
Before a move, the function checks whether the destination filename is already taken. It tries numbered alternatives until it finds a free name. This protects the existing destination file, but it does not prove that two differently named files have different contents. True duplicate detection would require comparing file hashes and belongs in a later project.
How to run the script safely
- Install Python 3 if it is not already installed.
- Create a small test folder and put copies of several files inside it.
- Temporarily replace Path.home() / "Downloads" with the path to that test folder.
- Keep DRY_RUN = True and run the script.
- Read every line beginning with WOULD MOVE.
- If each destination looks correct, change the setting to DRY_RUN = False.
- Run the script again, then inspect the resulting folders.
On Windows, open Command Prompt in the folder containing the script and run:
python organize_downloads.py
On macOS or Linux, the command may be:
python3 organize_downloads.py
Why this version is safer than a basic file sorter
On a phone, swipe the table left or right to view every column.
| Safety feature | Problem it prevents | How it works |
|---|---|---|
| Dry run | Moving files before you verify the rules | Prints planned actions while DRY_RUN is True |
| Collision handling | Replacing an existing file with the same name | Adds -1, -2, and so on until the destination is unique |
| Files only | Moving existing folders or recursively reorganizing them | Skips every item that is not a file |
| Other category | Crashing or ignoring an unknown extension | Sends unmatched file types to one review folder |
A worked example
Suppose Downloads contains report.pdf, photo.jpg, lesson.mp4, and notes.xyz. The first dry run prints a plan similar to this:
WOULD MOVE: report.pdf -> Documents/report.pdf
WOULD MOVE: photo.jpg -> Images/photo.jpg
WOULD MOVE: lesson.mp4 -> Videos/lesson.mp4
WOULD MOVE: notes.xyz -> Other/notes.xyz
If Images/photo.jpg already exists, the preview changes the destination to Images/photo-1.jpg. The original is not overwritten. This small detail makes the script suitable for learning on real folders after you have tested it with copies.
How to customise the categories
Edit the RULES dictionary to match your work. A student might add presentation formats to Documents. A creator might create Design and Project folders. Keep the leading dot in every extension and write extensions in lowercase.
If you want one folder per extension instead of broad categories, replace the category lookup with the extension name. Broad groups are easier for most people, while extension folders are better when a technical workflow needs strict separation.
This project uses the same practical automation mindset as our earlier guide to free keyword research with Python: start with a repetitive task, make the first version observable, and only automate the final action after checking the output.
Practical takeaway
Do not begin by scheduling this script to run automatically. First use a test folder, inspect the dry run, perform one real run, and confirm that duplicate names are handled correctly. Once you trust your rules, you can explore scheduling—but keep backups for valuable files and never automate deletion as a beginner project.
Frequently asked questions
How do I organize my Downloads folder with Python?
Use pathlib to list files, map each extension to a category, create destination folders, and move files with shutil.move. Preview the plan before enabling real moves.
Can Python automatically sort files by extension?
Yes. The suffix property returns a file’s extension. You can map extensions such as .jpg and .png to Images, then move each matching file into that folder.
Will this Python file organizer overwrite duplicate files?
No. This version checks whether the destination already exists. If it does, the script adds a number to the filename until it finds an unused destination.
Can I run the organizer automatically every day?
You can schedule a tested script with Windows Task Scheduler, cron, or another operating-system tool. Do that only after several successful manual runs, and keep the dry-run option available for rule changes.
Join the conversation
Post a Comment