Python File Organizer Script
Table of Contents + −
In the last lesson, API Data Fetcher, you pulled data from the web and saved it. Now we build a script that does a boring chore for you: tidying a messy folder. You know that Downloads folder full of images, PDFs, and zip files all jumbled together? This script sorts them into neat subfolders by type, in seconds. It is a real automation tool you will actually use, and it teaches you pathlib and shutil, the modern tools for working with files and folders.
🤔 Why automate file organizing?
Sorting files by hand is slow and dull. You drag images into one folder, PDFs into another, over and over. A computer is perfect for this kind of repetitive job. It never gets bored and never makes a typo.
Our script will:
- Look at every file in a folder.
- Check each file’s type from its extension, like
.jpgor.pdf. - Move it into a subfolder for that type, creating the subfolder if needed.
The key clue is the file extension, the bit after the dot in a file name, like .png or .txt. It tells you what kind of file it is. We will group files by their extension and move each one into a matching folder.
🧰 The tools: pathlib and shutil
Python has two modern, friendly tools for this job, both built in. Let’s meet them before building.
pathlib is the modern way to work with file paths. Instead of joining strings by hand, you get a Path object that knows how to list files, read names, and check types.
This shows pathlib listing a folder and reading a file’s parts:
from pathlib import Path
folder = Path("Downloads")
for file in folder.iterdir(): print(file.name, "->", file.suffix)Output
photo.jpg -> .jpgreport.pdf -> .pdfnotes.txt -> .txtSo folder.iterdir() gives you each item in the folder. file.name is the file name, and file.suffix is the extension, like .jpg. That suffix is exactly the clue we need to sort by.
shutil is a module for file operations like moving and copying. We use shutil.move to move a file into its new folder.
import shutil
# shutil.move(from_path, to_path) moves a file# We will use it to move each file into its type folderSo pathlib finds and inspects the files, and shutil moves them. Together they do the whole job.
🧩 Step 1: Mapping extensions to folder names
First we decide which extensions go into which folder. A dictionary maps each file type to a folder name. This keeps the rules in one clear place.
This dictionary sets up the sorting rules:
folders = { "Images": [".jpg", ".jpeg", ".png", ".gif"], "Documents": [".pdf", ".doc", ".docx", ".txt"], "Archives": [".zip", ".rar", ".tar"], "Videos": [".mp4", ".mov", ".avi"],}So each key is a folder name, and the value is a list of extensions that belong there. A .jpg or .png goes into “Images”. A .pdf goes into “Documents”. Keeping the rules in a dictionary makes it easy to add new types later, just by editing this one spot.
🔁 Step 2: The organizing function
Now the core. We go through each file in the folder, find which group its extension belongs to, and move it into that folder. We create the folder first if it does not exist.
This function does the sorting:
from pathlib import Pathimport shutil
def organize(folder_path, folders): folder = Path(folder_path)
for file in folder.iterdir(): if file.is_dir(): continue # skip folders, only handle files
moved = False for folder_name, extensions in folders.items(): if file.suffix.lower() in extensions: target = folder / folder_name target.mkdir(exist_ok=True) shutil.move(str(file), str(target / file.name)) print(f"Moved {file.name} to {folder_name}") moved = True break
if not moved: print(f"Skipped {file.name} (no matching folder)")Let’s walk through the important parts:
folder.iterdir()loops over everything in the folder. Wecontinuepast anything that is a folder, so we only move files.- For each file, we check every rule.
file.suffix.lower()gets the extension in lowercase, so.JPGand.jpgboth match. - When the extension is in a group’s list, we build the target folder path with
folder / folder_name. The/joins paths in pathlib, which is much cleaner than gluing strings. target.mkdir(exist_ok=True)creates that folder.exist_ok=Truemeans “do not complain if it already exists”.shutil.movemoves the file into the new folder, andbreakstops checking once it is placed.- If no rule matched, we say we skipped it, so nothing is moved by surprise.
Caution
This script moves real files on your computer. Test it on a copy of a folder first, or make a test folder with a few junk files. Once you trust it, run it on your real Downloads folder. Moving is not the same as deleting, but it is still good to be careful with real files.
🖥️ Step 3: The complete program
Here is the full organizer. Change target_folder to the folder you want to tidy. Save it as organizer.py and run it.
from pathlib import Pathimport shutil
folders = { "Images": [".jpg", ".jpeg", ".png", ".gif"], "Documents": [".pdf", ".doc", ".docx", ".txt"], "Archives": [".zip", ".rar", ".tar"], "Videos": [".mp4", ".mov", ".avi"],}
def organize(folder_path, folders): folder = Path(folder_path) if not folder.exists(): print("That folder does not exist.") return
for file in folder.iterdir(): if file.is_dir(): continue moved = False for folder_name, extensions in folders.items(): if file.suffix.lower() in extensions: target = folder / folder_name target.mkdir(exist_ok=True) shutil.move(str(file), str(target / file.name)) print(f"Moved {file.name} to {folder_name}") moved = True break if not moved: print(f"Skipped {file.name} (no matching folder)")
target_folder = "test_folder"organize(target_folder, folders)print("Done!")Here is a sample run on a messy test folder:
Output
Moved photo.jpg to ImagesMoved report.pdf to DocumentsMoved archive.zip to ArchivesMoved clip.mp4 to VideosSkipped readme.md (no matching folder)Done!In one run, the script sorted a jumbled folder into clean subfolders by type, and politely skipped the one file it had no rule for. That is real automation: a dull chore done perfectly in a second. Add more extensions to the dictionary and it handles even more types.
⚠️ Common Mistakes
A few traps in this project:
- Trying to move folders as if they were files. Without the
if file.is_dir(): continuecheck, the script could try to move a subfolder and cause errors. Skip folders. - Forgetting to create the target folder. Moving a file into a folder that does not exist fails.
target.mkdir(exist_ok=True)makes it first. - Matching extensions case-sensitively. A file named
PHOTO.JPGwould be missed if you compare without.lower(). Lowercase the suffix so all cases match.
✅ Best Practices
Habits this project teaches:
- Keep your sorting rules in a dictionary, so adding a new file type is a one-line change.
- Use
pathliband the/operator for paths, instead of joining strings, for clean and correct paths. - Use
exist_ok=Truewithmkdirso re-running the script does not crash on folders that already exist. - Test file-moving scripts on a copy first. Be careful whenever a program changes real files.
🧩 What You’ve Learned
✅ You built a script that automatically sorts a messy folder into subfolders by file type.
✅ pathlib’s Path lists files with iterdir() and reads the extension with .suffix.
✅ A dictionary maps each folder name to its list of extensions, keeping the rules in one place.
✅ target.mkdir(exist_ok=True) creates the folder safely, and shutil.move moves the file into it.
✅ Lowercasing the extension and skipping folders are the small checks that make the script reliable.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does file.suffix give you in pathlib?
Why: file.suffix returns the extension, the part after the dot. It is the clue used to decide which folder a file belongs in.
- 2
Why does the script use file.suffix.lower() when matching extensions?
Why: Extensions can be upper or lower case. Lowercasing the suffix means PHOTO.JPG and photo.jpg both match the .jpg rule.
- 3
What does target.mkdir(exist_ok=True) do?
Why: mkdir creates the target folder. exist_ok=True means it will not raise an error if the folder is already there, so re-runs are safe.
- 4
Why does the loop skip items where file.is_dir() is True?
Why: The script sorts files into type folders. Skipping directories avoids trying to move a subfolder, which would cause errors.
🚀 What’s Next?
You built a real automation tool that tidies files for you. Next we collect information from websites: a web scraper project that reads a page and pulls out the data you want.