Build a Smart File Organizer in Python
Use Claude Code as your AI pair programmer to build a Python file organizer.
Introduction
30 Second Summary
Everyone has a Downloads folder that slowly turns into digital chaos. Finding the file you need in a sea of random screenshots, PDFs, and code snippets is frustrating.
In this project, you will build a Python script that automatically sorts messy files into organized folders by type. You will use Claude Code as your AI pair programmer to write and test the code.
What You'll Build
A command-line tool called organizer.py that scans a target folder and moves files into categorized subfolders based on their file extension.
By the end of this project, you'll have:
- A working Python script that categorizes and moves files into labeled folders.
- A CLAUDE.md file configured so Claude Code remembers your project context across sessions.
- Hands-on experience using Claude Code to write, debug, and iterate on real code.
- Secret Mission: Add a dry-run preview mode and logging to your organizer.
Are there any prerequisites?
You need Python 3 installed on your computer and Claude Code installed with an Anthropic Pro plan. No prior Python experience is required.
Before We Start
Before We Start...
Set Up Your Project and CLAUDE.md
Every project needs a home folder to keep your work organized. Before you write any Python code, you need a dedicated directory with the right files in place.
You will also set up a special file called CLAUDE.md. Claude Code reads this file automatically at the start of every session, so it understands your project and preferences without you repeating yourself.
In this step, get ready to:
- Create your project folder with initial files.
- Write a CLAUDE.md file that teaches Claude Code about your project.
- Start Claude Code and verify it reads your project context.
Create your project folder and initialize it
Your project needs its own folder on your Desktop so you can find it easily. You will also create two empty files inside it to get started.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder, move into it, and create the initial files by running these commands:
macOS
mkdir file-organizer
cd file-organizer
touch organizer.py CLAUDE.md
Windows
mkdir file-organizer
cd file-organizer
New-Item organizer.py, CLAUDE.md -ItemType File
- Confirm the files exist by running:
ls
You should see organizer.py and CLAUDE.md listed in the output.
Don't see both files?
Make sure you ran the mkdir and cd commands first. If you see a "file already exists" error, the folder was already created from a previous attempt. Just cd file-organizer and create the missing files.
Help me troubleshoot my project folder setup
Write your CLAUDE.md file
CLAUDE.md is Claude Code's project memory. It gets loaded automatically at the start of every conversation, giving Claude Code persistent context about what you are building and how you like to work.
- Open CLAUDE.md in a text editor. You can use any editor you prefer (VS Code, Notepad, TextEdit).
- Replace the empty file contents with the following:
# File Organizer Project
This is a beginner Python project that builds a file organizer script.
## Project Overview
- We are building a command-line tool that sorts files into folders by type
- The main script is `organizer.py`
- We use only Python standard library modules (pathlib, shutil, os)
## Preferences
- I am a Python beginner. Explain concepts clearly when introducing them.
- Use pathlib for file path operations (modern Python style)
- Add comments to explain what each section does
- Use descriptive variable names
What does this file do?
The Project Overview section tells Claude Code what you are building and which modules you are using. This keeps its suggestions focused on the standard library instead of recommending third-party packages.
The Preferences section shapes how Claude Code communicates with you. Because you told it you are a beginner, it will add clear explanations whenever it introduces a new concept.
- Save CLAUDE.md.
- Verify the file has content by running this in your terminal:
macOS
cat CLAUDE.md
Windows
Get-Content CLAUDE.md
You should see the full contents of your CLAUDE.md printed in the terminal, starting with # File Organizer Project.
Seeing an empty output?
If nothing prints, the file is still empty. Make sure you saved after pasting the content. Check that you are in the file-organizer folder by running ls to confirm you see both files.
Help me figure out why my CLAUDE.md file is empty
✔️ Awesome, I've got everything!
Great. Double check you have saved your file, then move on to the next substep.
ⓧ I'd like to double check the full code
Here is the complete CLAUDE.md file. Make sure yours matches exactly:
# File Organizer Project
This is a beginner Python project that builds a file organizer script.
## Project Overview
- We are building a command-line tool that sorts files into folders by type
- The main script is `organizer.py`
- We use only Python standard library modules (pathlib, shutil, os)
## Preferences
- I am a Python beginner. Explain concepts clearly when introducing them.
- Use pathlib for file path operations (modern Python style)
- Add comments to explain what each section does
- Use descriptive variable names
Start Claude Code in your project
Claude Code runs directly in your terminal. When you launch it from inside your project folder, it automatically finds and reads your CLAUDE.md file.
- Make sure your terminal is still inside the file-organizer folder. Start Claude Code by running:
claude
What happens when Claude Code starts?
Claude Code opens an interactive session in your terminal. If this is your first time running it, it will prompt you to log in with your Anthropic account. Follow the on-screen instructions to authenticate.
Once it starts, Claude Code reads your CLAUDE.md automatically. You do not need to tell it to load the file.
- Verify Claude Code loaded your project context by typing this message into the Claude Code prompt:
What do you know about this project?
Claude Code should respond with details from your CLAUDE.md. It should mention the file organizer, Python standard library modules, and your beginner preferences.
Claude Code doesn't mention your project?
Make sure you started Claude Code from inside the file-organizer folder, not from your Desktop or home directory. Claude Code looks for CLAUDE.md in the current directory.
If Claude Code did not start at all, confirm it is installed by running claude --version in a new terminal window.
Help me get Claude Code to recognize my CLAUDE.md file
Your project is set up and Claude Code knows exactly what you are building. Next up, you will use Claude Code to write the file categorization logic that powers your organizer.
Build the File Categorization Logic
Your project is set up and Claude Code knows what you're building. Now it's time to write the core logic that decides where each file should go.
The organizer needs two things: a reference list of which file extensions belong to which category, and a function that looks up any given file in that list. You'll use Claude Code to build both pieces.
In this step, get ready to:
- Define a dictionary that maps file extensions to folder categories.
- Write a function that determines any file's category from its extension.
- Test the categorization logic with sample filenames.
Define a file category dictionary
A Python dictionary is the perfect data structure for this job. Each file extension (like .jpg) maps to a category name (like "Images"). When the organizer encounters a file, it looks up the extension in this dictionary to decide which folder to use.
- In your Claude Code session, type the following prompt:
In organizer.py, add a module docstring that says "Smart File Organizer - Automatically sorts files into categorized folders by file extension." Then import Path from pathlib, import shutil, and import os. Create a FILE_CATEGORIES dictionary that maps file extensions to category folder names. Include: Images (.jpg, .jpeg, .png, .gif, .bmp, .svg), Documents (.pdf, .doc, .docx, .txt, .xlsx, .pptx, .csv), Code (.py, .js, .html, .css, .java, .cpp), Audio (.mp3, .wav, .flac), Video (.mp4, .mov, .avi), and Archives (.zip, .rar, .7z).
Claude Code will ask for permission to edit organizer.py. Allow it.
Once Claude Code finishes, your organizer.py should contain code like this:
"""
Smart File Organizer
Automatically sorts files into categorized folders by file extension.
"""
from pathlib import Path
import shutil
import os
# Dictionary mapping file extensions to category folder names
FILE_CATEGORIES = {
# Images
".jpg": "Images",
".jpeg": "Images",
".png": "Images",
".gif": "Images",
".bmp": "Images",
".svg": "Images",
# Documents
".pdf": "Documents",
".doc": "Documents",
".docx": "Documents",
".txt": "Documents",
".xlsx": "Documents",
".pptx": "Documents",
".csv": "Documents",
# Code
".py": "Code",
".js": "Code",
".html": "Code",
".css": "Code",
".java": "Code",
".cpp": "Code",
# Audio
".mp3": "Audio",
".wav": "Audio",
".flac": "Audio",
# Video
".mp4": "Video",
".mov": "Video",
".avi": "Video",
# Archives
".zip": "Archives",
".rar": "Archives",
".7z": "Archives",
}
What does this code do?
The docstring at the top describes what the script does. The three imports bring in the tools you'll need later:
- Path from pathlib gives you an object-oriented way to work with file paths.
- shutil provides the file-moving function you'll use in the next step.
- os provides the function for creating folders.
The FILE_CATEGORIES dictionary uses file extensions as keys and folder names as values. When you look up ".jpg", the dictionary returns "Images". This single data structure powers the entire sorting logic.
- Open organizer.py in your editor to confirm the dictionary is there.
- Verify that each extension starts with a dot and maps to a category name like "Images", "Documents", "Code", "Audio", "Video", or "Archives".
Claude Code generated different categories?
Claude Code may organize the categories slightly differently. The exact extensions don't need to match perfectly at this stage, but make sure you have at least the six category names (Images, Documents, Code, Audio, Video, Archives) and that common extensions like .jpg, .pdf, and .py are included.
If key extensions are missing, tell Claude Code: "Add .bmp and .svg to Images, and .csv to Documents" to patch it up.
Why isn't Claude Code generating the dictionary I expected?
Write a function to determine a file's category
The dictionary holds the data, but you need a function to look things up in it. This function will take any filename, extract its extension, and return the matching category.
- In Claude Code, type this prompt:
Add a get_category() function below the dictionary. It should take a filename, use Path to extract the extension in lowercase, then look it up in FILE_CATEGORIES using .get() with a default of "Other" for unknown extensions.
Claude Code will add the function below your dictionary. It should look like this:
def get_category(filename):
"""Determine which category folder a file belongs to based on its extension."""
# Get the file extension in lowercase
extension = Path(filename).suffix.lower()
# Look up the extension in our dictionary
# If not found, default to "Other"
return FILE_CATEGORIES.get(extension, "Other")
What does this function do?
- Path(filename).suffix extracts the file extension including the dot. For "photo.jpg", it returns ".jpg".
- .lower() converts it to lowercase so ".JPG" and ".jpg" both match the same dictionary entry.
- .get(extension, "Other") looks up the extension in the dictionary. If it's not found, the function returns "Other" instead of crashing.
- Confirm that get_category() appears below the FILE_CATEGORIES dictionary in your file.
- Check that the function uses Path(filename).suffix.lower() and FILE_CATEGORIES.get().
Function uses os.path instead of pathlib?
Claude Code might use os.path.splitext() instead of Path().suffix. Both work, but your CLAUDE.md says to use pathlib. Tell Claude Code: "Refactor get_category to use Path(filename).suffix instead of os.path.splitext."
My get_category function doesn't look right. How do I fix it?
Test the logic with Claude Code
Before building more features, you should verify that your categorization logic actually works. Claude Code can run quick tests for you right inside the terminal.
- Ask Claude Code to test your function by typing this prompt:
Test the get_category function with these filenames: "photo.jpg", "report.pdf", "script.py", "song.mp3", "mystery.xyz". Print the result for each one.
What should I see?
Claude Code will run a quick test and show you the results. You should see output like:
- "photo.jpg" returns "Images".
- "report.pdf" returns "Documents".
- "script.py" returns "Code".
- "song.mp3" returns "Audio".
- "mystery.xyz" returns "Other" (because .xyz is not in the dictionary).
- Confirm that all five test filenames return the correct category.
- Pay special attention to "mystery.xyz". It should return "Other" since .xyz is not in your dictionary.
Test returning wrong categories?
If a filename returns the wrong category, check that the extension in your dictionary includes the leading dot (e.g., ".jpg" not "jpg"). Also confirm that .lower() is applied so uppercase extensions still match.
My test results look wrong. Help me debug get_category.
✔️ Awesome, I've got everything!
Great. Double check that you've saved organizer.py with the dictionary and the function.
ⓧ I'd like to double check the full code
Here is the full organizer.py file at this point. Compare yours against it:
"""
Smart File Organizer
Automatically sorts files into categorized folders by file extension.
"""
from pathlib import Path
import shutil
import os
# Dictionary mapping file extensions to category folder names
FILE_CATEGORIES = {
# Images
".jpg": "Images",
".jpeg": "Images",
".png": "Images",
".gif": "Images",
".bmp": "Images",
".svg": "Images",
# Documents
".pdf": "Documents",
".doc": "Documents",
".docx": "Documents",
".txt": "Documents",
".xlsx": "Documents",
".pptx": "Documents",
".csv": "Documents",
# Code
".py": "Code",
".js": "Code",
".html": "Code",
".css": "Code",
".java": "Code",
".cpp": "Code",
# Audio
".mp3": "Audio",
".wav": "Audio",
".flac": "Audio",
# Video
".mp4": "Video",
".mov": "Video",
".avi": "Video",
# Archives
".zip": "Archives",
".rar": "Archives",
".7z": "Archives",
}
def get_category(filename):
"""Determine which category folder a file belongs to based on its extension."""
# Get the file extension in lowercase
extension = Path(filename).suffix.lower()
# Look up the extension in our dictionary
# If not found, default to "Other"
return FILE_CATEGORIES.get(extension, "Other")
Your categorization engine is working. Next up, you'll build the function that actually moves files into the right folders.
Add File Moving Logic
Your file organizer now knows how to identify what category any file belongs to. The next piece of the puzzle is actually moving those files into the right folders.
In this step, you'll build the main engine of your organizer. This is the organize_files() function that loops through a folder, creates category subfolders, and moves each file to its new home.
In this step, get ready to:
- Write an organize_files() function that scans and sorts files.
- Add a main entry point so the script can run from the command line.
- Handle edge cases like duplicate filenames and directories.
Write the organize function
The core job of your organizer is to scan a folder, figure out where each file should go, and physically move it there. This requires looping through the folder's contents, calling your get_category() function for each file, and using shutil to perform the move.
- In Claude Code, ask it to write the organize function by entering this prompt:
Write an organize_files function in organizer.py that takes a source_folder parameter. It should use pathlib.Path to convert the folder path, check the folder exists, then loop through all items with iterdir(). For each file, call get_category to determine its category, create the category subfolder with os.makedirs if it doesn't exist, and move the file there with shutil.move. Print each file move and a final count.
Claude Code will update organizer.py. Your new function should look like this:
def organize_files(source_folder):
"""Sort all files in source_folder into categorized subfolders."""
source_path = Path(source_folder)
# Check that the source folder exists
if not source_path.exists():
print(f"Error: Folder '{source_folder}' does not exist.")
return
# Count how many files we move
moved_count = 0
# Loop through every item in the source folder
for item in source_path.iterdir():
# Skip directories, only process files
if item.is_dir():
continue
# Get the category for this file
category = get_category(item.name)
# Create the destination folder if it does not exist
destination_folder = source_path / category
os.makedirs(destination_folder, exist_ok=True)
# Build the destination file path
destination_path = destination_folder / item.name
# Handle duplicate filenames by adding a number
counter = 1
while destination_path.exists():
stem = item.stem
suffix = item.suffix
destination_path = destination_folder / f"{stem}_{counter}{suffix}"
counter += 1
# Move the file
shutil.move(str(item), str(destination_path))
moved_count += 1
print(f"Moved: {item.name} -> {category}/")
print(f"\nDone! Organized {moved_count} file(s).")
What does this code do?
- Path(source_folder) converts the folder name into a pathlib Path object so you can use methods like .exists() and .iterdir() on it.
- source_path.iterdir() yields every item (files and folders) inside the source folder, one at a time.
- os.makedirs(destination_folder, exist_ok=True) creates the category subfolder. The exist_ok=True part means it won't crash if the folder already exists.
- shutil.move() physically moves the file to its new location. It works across different drives, which is important on Windows.
- Confirm that organizer.py now contains the organize_files function below your existing get_category function.
Claude Code's output looks different?
Claude Code might generate slightly different variable names or comments. The important parts to check are: the function accepts a source_folder parameter, uses Path(source_folder), loops with .iterdir(), and moves files with shutil.move().
If the structure differs significantly, ask Claude Code to revise it: "Please update organize_files to match this structure" and paste the code from above.
Help me fix my organize_files function
Add a main entry point
Python scripts need an entry point that runs when you execute the file directly. The if __name__ == "__main__" pattern is how Python knows to start your code when you run python organizer.py from the terminal.
- In Claude Code, ask it to add the entry point:
Add an if __name__ == '__main__' block at the bottom of organizer.py that sets a variable folder_to_organize to 'test_messy_folder' and calls organize_files with it
The bottom of your file should now look like this:
if __name__ == "__main__":
# Set the folder to organize (change this to your target folder)
folder_to_organize = "test_messy_folder"
organize_files(folder_to_organize)
What is __name__ == "__main__"?
When you run a Python file directly (like python organizer.py), Python sets a special variable called __name__ to "__main__". This block ensures your code only runs when you execute the script directly, not when it's imported by another file.
The hardcoded "test_messy_folder" path points to a test folder you'll create in the next step. This keeps your real files safe while you experiment.
- Confirm that the if __name__ block appears at the very bottom of organizer.py, outside any function definition.
Entry point not at the bottom?
The if __name__ block must be at the bottom of the file, not indented inside a function. If Claude Code placed it elsewhere, tell it: "Move the if __name__ block to the very end of the file, outside all functions."
Help me position my main entry point correctly
Handle edge cases
A well-built script anticipates things that could go wrong. Your organizer needs to handle three common situations: folders mixed in with your files, duplicate filenames, and feedback about what happened.
- In Claude Code, ask it to verify and add edge case handling:
Check that organize_files handles these edge cases: 1) skip directories so it only moves files, 2) handle duplicate filenames by appending a number like _1 or _2, and 3) print a message for each file moved. Add any that are missing.
Let's confirm the three key safety checks are present in your organize_files function. Look for these sections:
The directory skip check:
# Skip directories, only process files
if item.is_dir():
continue
The duplicate filename handler:
# Handle duplicate filenames by adding a number
counter = 1
while destination_path.exists():
stem = item.stem
suffix = item.suffix
destination_path = destination_folder / f"{stem}_{counter}{suffix}"
counter += 1
The progress printing:
print(f"Moved: {item.name} -> {category}/")
print(f"\nDone! Organized {moved_count} file(s).")
Why do these edge cases matter?
- Skipping directories prevents the script from trying to move entire folders into category subfolders. Without this, your organized subfolders would get reorganized too.
- Duplicate handling prevents files from being silently overwritten. If you have two files named photo.jpg, the second becomes photo_1.jpg instead of replacing the first.
- Progress messages give you confidence the script is working correctly. You can see exactly what moved where.
- Save organizer.py and verify all three edge case blocks are present in your function.
Missing one of the edge cases?
If Claude Code didn't include the duplicate handling, paste this prompt: "Add a while loop in organize_files that checks if destination_path already exists. If it does, append _1, _2, etc. to the filename using item.stem and item.suffix."
If the is_dir() check is missing, ask: "Add a check at the start of the for loop that skips directories using item.is_dir() and continue."
Help me add edge case handling to my organizer
✔️ Awesome, I've got everything!
Double check you've saved organizer.py. Your file should have the imports, the dictionary, get_category(), organize_files(), and the if __name__ block at the bottom.
ⓧ I'd like to double check the full code
Here is the complete organizer.py at this point. Compare your file against this:
"""
Smart File Organizer
Automatically sorts files into categorized folders by file extension.
"""
from pathlib import Path
import shutil
import os
# Dictionary mapping file extensions to category folder names
FILE_CATEGORIES = {
# Images
".jpg": "Images",
".jpeg": "Images",
".png": "Images",
".gif": "Images",
".bmp": "Images",
".svg": "Images",
# Documents
".pdf": "Documents",
".doc": "Documents",
".docx": "Documents",
".txt": "Documents",
".xlsx": "Documents",
".pptx": "Documents",
".csv": "Documents",
# Code
".py": "Code",
".js": "Code",
".html": "Code",
".css": "Code",
".java": "Code",
".cpp": "Code",
# Audio
".mp3": "Audio",
".wav": "Audio",
".flac": "Audio",
# Video
".mp4": "Video",
".mov": "Video",
".avi": "Video",
# Archives
".zip": "Archives",
".rar": "Archives",
".7z": "Archives",
}
def get_category(filename):
"""Determine which category folder a file belongs to based on its extension."""
# Get the file extension in lowercase
extension = Path(filename).suffix.lower()
# Look up the extension in our dictionary
# If not found, default to "Other"
return FILE_CATEGORIES.get(extension, "Other")
def organize_files(source_folder):
"""Sort all files in source_folder into categorized subfolders."""
source_path = Path(source_folder)
# Check that the source folder exists
if not source_path.exists():
print(f"Error: Folder '{source_folder}' does not exist.")
return
# Count how many files we move
moved_count = 0
# Loop through every item in the source folder
for item in source_path.iterdir():
# Skip directories, only process files
if item.is_dir():
continue
# Get the category for this file
category = get_category(item.name)
# Create the destination folder if it does not exist
destination_folder = source_path / category
os.makedirs(destination_folder, exist_ok=True)
# Build the destination file path
destination_path = destination_folder / item.name
# Handle duplicate filenames by adding a number
counter = 1
while destination_path.exists():
stem = item.stem
suffix = item.suffix
destination_path = destination_folder / f"{stem}_{counter}{suffix}"
counter += 1
# Move the file
shutil.move(str(item), str(destination_path))
moved_count += 1
print(f"Moved: {item.name} -> {category}/")
print(f"\nDone! Organized {moved_count} file(s).")
if __name__ == "__main__":
# Set the folder to organize (change this to your target folder)
folder_to_organize = "test_messy_folder"
organize_files(folder_to_organize)
Your organizer script is now complete and ready to sort files. Next up, you'll create a test folder full of sample files and watch the organizer do its thing.
Test Your Organizer
Your organizer script has all the logic it needs to sort files by type. But you haven't seen it run on actual files yet.
Testing with dummy files in a safe folder lets you verify everything works before pointing the script at your real Downloads folder.
In this step, get ready to:
- Create a test folder with sample files of different types.
- Run your organizer script and watch it sort files.
- Verify each file ended up in the correct category folder.
Create a test folder with sample files
Your organizer needs files to organize. You'll create a test_messy_folder directory inside your project and fill it with dummy files that each have a different extension.
- Create the test folder and sample files by running these commands in your terminal:
macOS
mkdir test_messy_folder
touch test_messy_folder/photo.jpg test_messy_folder/report.pdf test_messy_folder/script.py test_messy_folder/song.mp3 test_messy_folder/notes.txt
Windows
mkdir test_messy_folder
New-Item test_messy_folder/photo.jpg
New-Item test_messy_folder/report.pdf
New-Item test_messy_folder/script.py
New-Item test_messy_folder/song.mp3
New-Item test_messy_folder/notes.txt
What do these files test?
Each file has a different extension that maps to a different category in your FILE_CATEGORIES dictionary.
- photo.jpg maps to "Images".
- report.pdf and notes.txt map to "Documents".
- script.py maps to "Code".
- song.mp3 maps to "Audio".
- Confirm the files exist by running:
ls test_messy_folder
- You should see all five files listed: photo.jpg, report.pdf, script.py, song.mp3, and notes.txt.
Don't see the files?
- Make sure you're running the commands from inside your file-organizer directory. Run pwd (macOS) or cd (Windows) to check your current location.
- On Windows, if ls does not work, try dir test_messy_folder instead. The ls command works in PowerShell but not in CMD.
- help me troubleshoot why my test files aren't showing up in the test_messy_folder directory
Run the organizer
Your test folder is ready. Time to run the script and watch it sort everything.
- Run your organizer script by executing this command:
python organizer.py
What should I see?
Your terminal should display a message for each file moved, followed by a summary count:
Moved: photo.jpg -> Images/
Moved: report.pdf -> Documents/
Moved: script.py -> Code/
Moved: song.mp3 -> Audio/
Moved: notes.txt -> Documents/
Done! Organized 5 file(s).
The order of files might differ slightly, but you should see all 5 files moved and the final count message.
python3 on macOS
If you see "command not found" when running python, try python3 organizer.py instead. On macOS, the python3 command is often required.
Seeing an error instead?
- If you see Error: Folder 'test_messy_folder' does not exist. then the test folder was not created in the right location. Make sure you're running the command from the file-organizer directory (same folder that contains organizer.py).
- If you see a SyntaxError or IndentationError, there is a typo or spacing issue in organizer.py. Ask Claude Code to check the file for errors.
- help me debug an error when running python organizer.py
Verify the results
The terminal output told you files were moved, but you should confirm the folder structure matches your expectations.
- Check what subfolders were created by running:
ls test_messy_folder
- You should see four category folders: Audio, Code, Documents, and Images.
- Verify a specific category by checking its contents:
ls test_messy_folder/Documents
- You should see report.pdf and notes.txt together in the Documents folder.
- Check the other folders too:
ls test_messy_folder/Images
ls test_messy_folder/Code
ls test_messy_folder/Audio
What should I see in each folder?
- Images contains photo.jpg.
- Code contains script.py.
- Audio contains song.mp3.
- Documents contains both report.pdf and notes.txt (two files sharing the same category).
Files not in the right folders?
- If a file ended up in "Other" instead of its expected category, check that the extension in your FILE_CATEGORIES dictionary matches the file's extension exactly (including the dot).
- If the folders are empty, check that shutil.move in your script uses str(item) and str(destination_path) as arguments.
- help me figure out why my files are not sorted into the correct category folders
If every file is in its correct category folder, your organizer is working perfectly.
✔️ Awesome, I've got everything!
Great. Double check you've saved organizer.py and confirmed all five files are in their correct category folders.
ⓧ I'd like to double check the full code
Here is the complete organizer.py file. Make sure yours matches exactly:
"""
Smart File Organizer
Automatically sorts files into categorized folders by file extension.
"""
from pathlib import Path
import shutil
import os
# Dictionary mapping file extensions to category folder names
FILE_CATEGORIES = {
# Images
".jpg": "Images",
".jpeg": "Images",
".png": "Images",
".gif": "Images",
".bmp": "Images",
".svg": "Images",
# Documents
".pdf": "Documents",
".doc": "Documents",
".docx": "Documents",
".txt": "Documents",
".xlsx": "Documents",
".pptx": "Documents",
".csv": "Documents",
# Code
".py": "Code",
".js": "Code",
".html": "Code",
".css": "Code",
".java": "Code",
".cpp": "Code",
# Audio
".mp3": "Audio",
".wav": "Audio",
".flac": "Audio",
# Video
".mp4": "Video",
".mov": "Video",
".avi": "Video",
# Archives
".zip": "Archives",
".rar": "Archives",
".7z": "Archives",
}
def get_category(filename):
"""Determine which category folder a file belongs to based on its extension."""
# Get the file extension in lowercase
extension = Path(filename).suffix.lower()
# Look up the extension in our dictionary
# If not found, default to "Other"
return FILE_CATEGORIES.get(extension, "Other")
def organize_files(source_folder):
"""Sort all files in source_folder into categorized subfolders."""
source_path = Path(source_folder)
# Check that the source folder exists
if not source_path.exists():
print(f"Error: Folder '{source_folder}' does not exist.")
return
# Count how many files we move
moved_count = 0
# Loop through every item in the source folder
for item in source_path.iterdir():
# Skip directories, only process files
if item.is_dir():
continue
# Get the category for this file
category = get_category(item.name)
# Create the destination folder if it does not exist
destination_folder = source_path / category
os.makedirs(destination_folder, exist_ok=True)
# Build the destination file path
destination_path = destination_folder / item.name
# Handle duplicate filenames by adding a number
counter = 1
while destination_path.exists():
stem = item.stem
suffix = item.suffix
destination_path = destination_folder / f"{stem}_{counter}{suffix}"
counter += 1
# Move the file
shutil.move(str(item), str(destination_path))
moved_count += 1
print(f"Moved: {item.name} -> {category}/")
print(f"\nDone! Organized {moved_count} file(s).")
if __name__ == "__main__":
# Set the folder to organize (change this to your target folder)
folder_to_organize = "test_messy_folder"
organize_files(folder_to_organize)
Secret mission
Add Dry-Run Mode and Logging
Your organizer works, but what if you want to preview changes before committing? Real automation tools always have a safety net. Add a dry-run mode that shows what would happen without touching any files, plus a log file that records every run.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally using Python's standard library, so there are no ongoing costs. Decide whether to keep your project files for future use, or delete them entirely.
Resources you used:
- file-organizer project folder on your Desktop.
- organizer.py script (the file organizer tool).
- CLAUDE.md project memory file.
- test_messy_folder directory with sample files and organized subfolders.
- Claude Code CLI (installed on your system).
Keep everything running
No action needed. Choose this if you want to keep using your file organizer or continue building on it.
- Your file-organizer folder stays on your Desktop, ready to use anytime.
- You can point organizer.py at any folder (like your real Downloads) by changing the folder_to_organize variable.
- Claude Code remains installed and usable for other projects.
Pause - I'll come back to this later
Since everything is local files, there is nothing to pause or shut down. Your project folder will sit quietly on your Desktop until you return.
- Leave the file-organizer folder where it is.
- When you come back, open your terminal, navigate to the folder, and run claude to pick up where you left off.
- Your CLAUDE.md file ensures Claude Code remembers your project context.
Delete - I don't want to use this again
Remove all project files from your system. Claude Code itself stays installed for future projects.
- Delete the entire file-organizer folder from your Desktop.
- On Windows, right-click the folder and select Delete. On macOS, drag it to the Trash.
- This removes organizer.py, CLAUDE.md, and the test_messy_folder directory along with all sample files.
- If you want to uninstall Claude Code entirely, follow the uninstall instructions for your platform.
Nice Work!
Nice Work!
You just built your first Python automation tool using Claude Code as your AI pair programmer.
Here is what you accomplished:
- Built a working file organizer script that categorizes and moves files using Python's pathlib, shutil, and os modules.
- Configured a CLAUDE.md file that gives Claude Code persistent project memory across sessions.
- Used Claude Code to write, test, and iterate on real Python code from scratch.
- Secret Mission: Added a dry-run preview mode and file logging with argparse.
Ready to quiz yourself?