File Organizer V7.0: the Ultimate Guide

by derekamckiernan in Circuits > Microsoft

21 Views, 0 Favorites, 0 Comments

File Organizer V7.0: the Ultimate Guide

AdobeStock_416057612-e1665052015417.jpg

📦 File Organizer v7.0: The Ultimate Guide

Welcome to File Organizer v7.0 for Windows! This powerful yet simple tool is designed to bring order to your digital chaos. Whether it's your Downloads folder, a messy project directory, or your desktop, this guide will walk you through setting up a fully automated, one-click organization system.

Let's get started!

Supplies

Essential Supplies (The Must-Haves)

These are the non-negotiable items you'll need to complete the guide.

  1. A Windows Computer: Since this is the "Windows Edition," you'll need a laptop or desktop running a modern version of Windows (like Windows 10 or 11). It doesn't need to be powerful; any standard school or personal computer will do just fine.
  2. Internet Connection: You will need this to download Python from the official website and to install the required libraries using the $pip$ command.
  3. Administrator Privileges: On the computer you're using, you'll need permission to install software (Python) and run the Command Prompt as an administrator. If you're using a school computer, you might need to ask your IT department for assistance with this step.
  4. A Basic Text Editor: You need a program to create and edit the script and configuration files. Your computer already has one!
  5. Good enough: Notepad (built into Windows)
  6. Better (and free): Visual Studio Code or Notepad++. These offer features like syntax highlighting that make reading code much easier.

Helpful Extras (The "Nice-to-Haves")

These aren't strictly required, but they will make the project more effective and educational.

  1. A Messy Folder to Organize: The best way to see your project work is to have a real-world problem to solve! Your own $Downloads$ folder is usually the perfect test subject, filled with a mix of documents, images, installers, and archives.
  2. An External Drive or USB Stick for Backups: Before you run the script for the first time on an important folder, it's a wise idea to back up your files. This is a great habit for any programming project.
  3. Curiosity and an Idea: The project becomes truly yours when you customize the $config.yaml$ file. Think about what you want to organize.
  4. Are you a gamer? Create rules for screenshots and video captures.
  5. Do you have lots of schoolwork? Make categories for different subjects like "History," "Math," or "Science."
  6. Are you a budding artist? Sort your .psd, .kra, or .ai files into a "Creative Projects" folder.

The Most Important "Supply" of All

  1. Patience and Attention to Detail: Following programming instructions requires careful reading. If you get an error, don't be discouraged! Read the message carefully and check your steps. Double-checking file names, commands, and folder paths is the key to success.

Laying the Foundation

Step 1: Laying the Foundation

First, let's create a dedicated home for your new organizer. This central folder will contain all the necessary scripts and configuration files.

  1. Create a new folder in a simple, accessible location. For example: $C:\FileOrganizer$

This folder is now your command center.

Assembling Your Toolkit

Step 2: Assembling Your Toolkit

You'll need a few files to get the organizer running. Place all of them inside your $C:\FileOrganizer$ folder.

File Name and Purpose

file_organizer_v7_windows_edition.py. The main Python script—the brains of the operation.

config.yaml. The rulebook where you define folders, file types, and custom logic.

Start Organizer.bat. A one-click batch file to run the organizer effortlessly.

icon_generator.py (Optional). A handy script to create a custom .ico file for your shortcuts.

organizer.ico (Optional). The default icon, or the one you create in Step 6.



Installing the Engine (Python & Dependencies)

Step 3: Installing the Engine (Python & Dependencies)

If you don't already have Python, you'll need to install it. It's the engine that powers our script.


Download and Install Python:


Visit python.org and download Python 3.7 or a newer version.

During installation, it is crucial that you check the box that says "Add Python to PATH".

Install Required Libraries:


Open the Command Prompt with administrative privileges. (Press Win + R, type cmd, then press Ctrl + Shift + Enter).

Copy and paste the following command and press Enter to install the necessary packages:

Bash


pip install PyYAML colorama tqdm pyfiglet plyer pillow

(Note: pillow is only required for the optional icon generator.)

Adding the Main Script

Step 4: Adding the Main Script

This is the core Python script that does all the heavy lifting.

  1. Inside your $C:\FileOrganizer$ folder, create a new file named $file_organizer_v7_windows_edition.py$.
  2. Copy the entire code block below and paste it into this file.

Python


import os
import shutil
import time
import logging
import argparse
import sys
import yaml
import fnmatch
import platform
import ctypes
from pathlib import Path
from datetime import datetime
from collections import Counter
from logging.handlers import RotatingFileHandler

# --- Optional/Enhanced Dependencies ---
try:
from plyer import notification
PLYER_INSTALLED = True
except ImportError:
PLYER_INSTALLED = False

try:
import colorama
colorama.init(autoreset=True)
COLORAMA_INSTALLED = True
except ImportError:
COLORAMA_INSTALLED = False

try:
from tqdm import tqdm
TQDM_INSTALLED = True
except ImportError:
TQDM_INSTALLED = False

try:
import pyfiglet
PYFIGLET_INSTALLED = True
except ImportError:
PYFIGLET_INSTALLED = False

# --- Colored Logging Setup ---
class ColoredFormatter(logging.Formatter):
if COLORAMA_INSTALLED:
COLORS = {
'WARNING': colorama.Fore.YELLOW,
'INFO': colorama.Fore.CYAN,
'DEBUG': colorama.Fore.BLUE,
'ERROR': colorama.Fore.RED,
'CRITICAL': colorama.Fore.RED + colorama.Style.BRIGHT,
}
else:
COLORS = {}

def format(self, record):
log_message = super().format(record)
if hasattr(self, 'COLORS'):
return self.COLORS.get(record.levelname, '') + log_message
return log_message

def show_windows_error_popup(title, message):
"""Displays a native Windows error message box if on Windows."""
if platform.system() == "Windows":
ctypes.windll.user32.MessageBoxW(0, message, title, 0x10)

def print_splash_screen():
"""Prints ASCII art title if pyfiglet is installed."""
if PYFIGLET_INSTALLED:
title = pyfiglet.figlet_format("File Organizer", font="slant")
splash = (colorama.Fore.CYAN + title) if COLORAMA_INSTALLED else title
print(splash)
version_text = "Version 7.0 (Windows Edition)\n"
print((colorama.Style.BRIGHT + version_text) if COLORAMA_INSTALLED else version_text)
else:
print("--- File Organizer v7.0 ---")

def is_relative_to(path, base):
"""Backward-compatible check for Python <3.9."""
try:
path.relative_to(base)
return True
except ValueError:
return False

def load_config(config_path):
"""Loads and returns the YAML configuration file."""
try:
with open(config_path, 'r') as f:
return yaml.safe_load(f)
except FileNotFoundError:
logging.error(f"Configuration file not found at: {config_path}")
show_windows_error_popup("Configuration Error", f"Could not find '{config_path}'. Please ensure the file exists.")
sys.exit(1)
except yaml.YAMLError as e:
logging.error(f"Error parsing YAML configuration file: {e}")
show_windows_error_popup("Configuration Error", "The config.yaml file is malformed. Please check its syntax.")
sys.exit(1)

def validate_config(config):
"""Performs validation checks on the loaded configuration."""
if not config or 'source_folder' not in config or not config['source_folder']:
logging.error("Config validation failed: 'source_folder' is required and must not be empty.")
return False
return True

def setup_logging(config, log_level_str):
"""Configures logging for console and file."""
log_level = getattr(logging, log_level_str.upper(), logging.INFO)
log_path = Path(config.get('log_file_path', 'organizer.log'))
log_path.parent.mkdir(parents=True, exist_ok=True)
file_handler = RotatingFileHandler(
log_path,
maxBytes=config.get('log_file_max_bytes', 5*1024*1024),
backupCount=config.get('log_file_backup_count', 5),
encoding='utf-8'
)
file_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
console_handler = logging.StreamHandler()
console_handler.setFormatter(ColoredFormatter('%(levelname)s: %(message)s'))
root_logger = logging.getLogger()
root_logger.setLevel(log_level)
root_logger.handlers = [file_handler, console_handler]

def organize_folder(config, args):
"""Main function to organize files, with progress bar and summary."""
start_time = time.time()
source_folder = Path(args.source or config['source_folder']).resolve()
logging.info(f"Starting scan of '{source_folder}'...")

# --- Rule and Exclusion Setup ---
exclusion_patterns = config.get('exclusion_patterns', [])
log_file_path = Path(config.get('log_file_path')).resolve()
if is_relative_to(log_file_path, source_folder):
exclusion_patterns.append(log_file_path.name)
dest_folders = {source_folder / cat for cat in config.get('file_type_mappings', {})}
dest_folders.update({source_folder / cat for cat in config.get('custom_rules', {})})
dest_folders.add(source_folder / config.get('unsorted_folder_name', 'Unsorted'))

# --- File Discovery ---
files_to_process = []
file_iterator = source_folder.rglob('*') if args.recursive else source_folder.iterdir()
for item in file_iterator:
is_in_dest_folder = any(item.parent == dest_folder or is_relative_to(item.parent, dest_folder) for dest_folder in dest_folders)
if item.is_file() and not is_in_dest_folder:
files_to_process.append(item)
logging.info(f"Scan complete. Found {len(files_to_process)} files to process.")
if not TQDM_INSTALLED and len(files_to_process) > 0:
logging.warning("`tqdm` not installed. Progress bar will not be shown. (pip install tqdm)")

stats = Counter()
# --- File Processing ---
progress_bar = tqdm(files_to_process, desc="Organizing", unit="file", ncols=100, disable=not TQDM_INSTALLED)
for item in progress_bar:
if config.get('exclude_hidden_files', True) and item.name.startswith('.'):
stats['excluded'] += 1; continue
if any(fnmatch.fnmatchcase(item.name.lower(), p.lower()) for p in exclusion_patterns):
stats['excluded'] += 1; continue

destination_category = None
file_name_lower = item.name.lower()
if config.get('custom_rules'):
for category, keywords in config.get('custom_rules').items():
if any(k.lower() in file_name_lower for k in keywords):
destination_category = category; break
if not destination_category and config.get('file_type_mappings'):
ext = item.suffix.lower()
for category, extensions in config.get('file_type_mappings').items():
if ext in extensions:
destination_category = category; break
destination_category = destination_category or config.get('unsorted_folder_name', 'Unsorted')

stats['processed'] += 1; stats[f'moved_to_{destination_category}'] += 1
if args.verbose_dry_run:
logging.info(f"[DRY RUN] Would move '{item.name}' to '{source_folder / destination_category}'")
continue
if not args.dry_run:
try:
dest_folder = source_folder / destination_category
dest_folder.mkdir(parents=True, exist_ok=True)
dest_path = dest_folder / item.name
if dest_path.exists():
new_name = f"{item.stem}_{datetime.now().strftime('%Y%m%d_%H%M%S')}{item.suffix}"
dest_path = dest_folder / new_name
shutil.move(str(item), str(dest_path))
except Exception as e:
progress_bar.write(f"ERROR: Could not move '{item.name}'. Reason: {e}", file=sys.stderr)
stats['errors'] += 1; stats[f'moved_to_{destination_category}'] -= 1
# --- Final Summary ---
duration = time.time() - start_time; total_moved = stats['processed'] - stats['errors']
if stats['errors'] == 0:
final_message = colorama.Style.BRIGHT + colorama.Fore.GREEN + f"\nâś” All operations complete!" if COLORAMA_INSTALLED else "\nâś” All operations complete!"
else:
final_message = colorama.Style.BRIGHT + colorama.Fore.YELLOW + f"\nâš  Completed with {stats['errors']} error(s)." if COLORAMA_INSTALLED else f"\nâš  Completed with {stats['errors']} error(s)."
print(final_message)
logging.info("--- FINAL SUMMARY ---")
logging.info(f"Duration: {duration:.2f}s | Processed: {stats['processed']} | Moved: {total_moved} | Excluded: {stats['excluded']} | Errors: {stats['errors']}")

def main():
"""Main entry point for the command-line tool."""
epilog_text = """
Dependencies:
PyYAML, colorama, tqdm, pyfiglet, plyer (Optional)

Typical Usage:
1. Full recursive organization:
python file_organizer_v7_windows_edition.py --recursive
2. Test rules without moving files (dry run):
python file_organizer_v7_windows_edition.py --recursive --dry-run
3. See every planned move (verbose dry run):
python file_organizer_v7_windows_edition.py --recursive --verbose-dry-run
"""
parser = argparse.ArgumentParser(description="A professional, configurable file organizer.", epilog=epilog_text, formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('--config', default='config.yaml', help='Path to the configuration file.')
parser.add_argument('--source', help='Override the source folder from the config file.')
parser.add_argument('--dry-run', action='store_true', help='Simulate organization without moving any files.')
parser.add_argument('--verbose-dry-run', action='store_true', help='Show every planned move during a dry run.')
parser.add_argument('--log-level', default='INFO', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], help='Set the console logging level.')
parser.add_argument('--recursive', action='store_true', help='Recursively organize all subfolders.')
args = parser.parse_args()

print_splash_screen()
config = load_config(args.config)
setup_logging(config, args.log_level)
if not validate_config(config):
show_windows_error_popup("Configuration Error", "The configuration file has critical errors. Please see the log.")
sys.exit(1)
organize_folder(config, args)

if __name__ == '__main__':
main()


Creating Your Rulebook (config.yaml)

Step 5: ⚙️ Creating Your Rulebook (config.yaml)

This is where the magic happens! The $config.yaml$ file tells the script what to organize and how. Create this file in your $C:\FileOrganizer$ folder and paste in the example content below.

Customize this file to fit your needs!

  1. source_folder: The directory you want to clean up (e.g., your Downloads folder).
  2. custom_rules: Sort files based on keywords in their names. Perfect for invoices, reports, or screenshots.
  3. file_type_mappings: The primary way to sort files—by their extension (e.g., .jpg, .pdf, .zip).

YAML


# The folder you want the script to organize.
source_folder: "C:/Users/YourName/Downloads"

# --- Logging & General Settings ---
log_file_path: "C:/FileOrganizer/organizer.log"
log_file_max_bytes: 5242880 # 5 MB
log_file_backup_count: 5
unsorted_folder_name: "Unsorted"
exclude_hidden_files: true

# --- File Exclusion Rules ---
# Files matching these patterns will be ignored.
exclusion_patterns:
- "*.tmp"
- "*.crdownload"
- ".~*"
- "*.part"

# --- Custom Rules (Keyword-Based) ---
# Sorts files if their name contains these keywords. This runs BEFORE file type mapping.
custom_rules:
Finance: ["invoice", "receipt", "statement"]
Screenshots: ["screenshot", "capture"]
Work_Documents: ["report", "project", "proposal"]

# --- File Type Mappings (Extension-Based) ---
# The main sorting logic. Maps file extensions to destination folders.
file_type_mappings:
Images: [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".svg"]
Documents: [".pdf", ".doc", ".docx", ".txt", ".rtf", ".odt", ".xls", ".xlsx", ".ppt", ".pptx"]
Archives: [".zip", ".rar", ".7z", ".tar", ".gz"]
Audio: [".mp3", ".wav", ".aac", ".flac"]
Video: [".mp4", ".mov", ".avi", ".mkv"]
Scripts: [".py", ".js", ".html", ".css", ".sh", ".bat"]
Software: [".exe", ".msi", ".dmg", ".pkg"]


Giving Your Organizer a Custom Look

🚀 Going Further: Optional Enhancements

The core setup is complete! The following steps are optional but highly recommended for the best experience.

(Optional) Step 6: Giving Your Organizer a Custom Look

Create a unique icon for your organizer. Save the following code as $icon_generator.py$ in your project folder.

Python


from PIL import Image, ImageDraw, ImageFont

def create_icon(text="FO", filename="organizer.ico"):
img = Image.new('RGBA', (256, 256), (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
background_color = "#3498db"; text_color = "#ffffff"
try: font = ImageFont.truetype("arialbd.ttf", 150)
except IOError: font = ImageFont.load_default()
draw.rounded_rectangle((0, 0, 256, 256), fill=background_color, radius=40)
draw.text((128, 128), text, fill=text_color, font=font, anchor="mm")
img.save(filename, format='ICO', sizes=[(32, 32), (48, 48), (64, 64), (256, 256)])
print(f"Icon '{filename}' created successfully!")

if __name__ == '__main__':
create_icon()

Run it from the Command Prompt: python icon_generator.py

Creating a One-Click Shortcut

(Recommended) Step 7: Creating a One-Click Shortcut

This batch file makes running the organizer incredibly simple.

  1. Create a file named $Start Organizer.bat$ in your project folder.
  2. Paste in this code: Code snippet

@echo off
title File Organizer v7.0
cd /d "%~dp0"
python file_organizer_v7_windows_edition.py --recursive
echo.
echo Operation finished. You can close this window.
pause
  1. Right-click the $Start Organizer.bat$ file and select Send to > Desktop (create shortcut).
  2. You can now right-click your new desktop shortcut, go to Properties, and use Change Icon... to select your custom $organizer.ico$.


Going Pro - Building a Standalone App (.EXE)

(Advanced) Step 8: Going Pro - Building a Standalone App (.EXE)

For ultimate portability, you can compile the script into a single .exe file that doesn't require a Python installation to run.

  1. Install the PyInstaller library: pip install pyinstaller
  2. From your project folder, run this command: pyinstaller --onefile --icon=organizer.ico file_organizer_v7_windows_edition.py
  3. Your standalone application will be waiting for you in the newly created dist folder.


Set It and Forget It - Automating With Task Scheduler

(Advanced) Step 9: Set It and Forget It - Automating with Task Scheduler

Run the organizer automatically on a schedule (e.g., daily).

  1. Open Task Scheduler (Press Win + R, type taskschd.msc, and press Enter).
  2. In the Actions pane, click Create Task....
  3. On the Actions tab: Click New... and set the following:
  4. Program/script: Browse to your $Start Organizer.bat$ file or the .exe you created.
  5. Start in (optional): Enter the full path to your project folder (e.g., $C:\FileOrganizer$). This is crucial for the script to find its config.yaml.
  6. On the Triggers tab: Set up a schedule for how often you want the task to run.


đź’ˇ Troubleshooting & Pro-Tips

ProblemSolution

"ModuleNotFoundError"

You missed a dependency. Run the pip install ... command from Step 3 again.

"config.yaml not found"

The script can't find its rulebook. Ensure the script is being run from your project folder. Using the .bat file or setting the "Start in" property for shortcuts/tasks solves this.

Script closes instantly

Run it using the $Start Organizer.bat$ file, which includes a pause command to keep the window open after it finishes.

Progress bar is missing

The tqdm library might not be installed. Run pip install tqdm.

Scheduled task fails

The most common cause is the "Start in" field being empty. Edit the task and set it to your project folder path.

Export to Sheets

Pro-Tips:

  1. Safety First: Before a full run, test your rules with a dry run! Use the command python file_organizer_v7_windows_edition.py --recursive --dry-run. For even more detail, use the --verbose-dry-run flag.
  2. Easy Migration: To use the organizer on a new PC, just copy the entire project folder and update the source_folder path in $config.yaml$.

🎉 Congratulations!

You now have a powerful, customizable, and automated file organization system for Windows. Enjoy your clean and tidy folders!