Background application for Windows that automatically sorts new files appearing on your Desktop or in the Downloads folder into configurable target directories. Runs silently, uses near-zero CPU when idle, and logs every move.
Includes a GUI control panel (File Sorter Manager.exe) with config editor,
live log viewer, and process management — with English / Russian localization.
| Edition | Versions |
|---|---|
| Windows 11 | 21H2, 22H2, 23H2, 24H2 — all editions (Home, Pro, Enterprise) |
| Windows 10 | 1607 through 22H2 — all editions |
| Windows Server | 2016, 2019, 2022, 2025 |
Works on any Windows release that supports Python 3.8+ and NTFS. The underlying
ReadDirectoryChangesW WinAPI used by watchdog has been present since
Windows 2000, so even older builds are supported in practice.
- Python 3.8+ — python.org
- Make sure Add Python to PATH is checked during installation
- pip — included with Python
Everything else is installed automatically by install.bat.
- Edit
config.jsonor use GUI (File Sorter Manager.exe) — set your watch directories, target folders, and rules via GUI or any text editor. - Run
install.bat(as Administrator recommended) — installs dependencies, saves Python path, and creates a Task Scheduler job - Reboot or log out/in — the sorter starts automatically
- To start immediately without reboot: run
restart.bator click Start in the GUI
After that the sorter runs silently in the background. Drop a file on the Desktop and it moves to the configured folder within seconds.
Launch File Sorter Manager.exe (built from gui.py via build_exe.bat).
The GUI is a standalone control panel — it does NOT need to run alongside the sorter. It provides:
- Config editor — edit watch directories, rules, unsorted path, ignore patterns, and settings with Browse buttons for folder selection
- Live log viewer — tail the latest log file with color-coded levels (ERROR/WARNING/INFO/DEBUG), auto-refresh
- Process management — Start / Stop / Restart buttons with live status
- Validation — check config for errors before saving
- Localization — toggle between English and Russian (button in sidebar)
All changes are written directly to config.json. The sorter reads the config
fresh on every launch — no restart needed if it's already running (just toggle
Restart).
All settings are in a single file. Changing the config and restarting the sorter applies changes immediately.
| Key | Type | Default | Description |
|---|---|---|---|
watch_directories |
list[str] |
required | Folders to monitor for new files |
unsorted_directory |
str |
required | Where files with no matching rule go |
rules |
dict[str,str] |
required | Pattern → destination mappings |
debounce_seconds |
float |
2.0 |
Delay after last write before moving |
log_file |
str |
"file_sorter.log" |
Base path for log files |
max_log_files |
int |
20 |
How many old log files to keep (cleanup on startup) |
quiet |
bool |
true |
If true, suppress console output |
sort_existing_on_start |
bool |
true |
Process pre-existing files at startup |
debug |
bool |
false |
Enable debug-level messages in log files |
ignore_patterns |
list[str] |
see below | Files matching these patterns are never moved |
All paths support environment variables:
%USERNAME%— current user name%USERPROFILE%— e.g.C:\Users\John%HOMEPATH%,%APPDATA%,%LOCALAPPDATA%, etc.
Each rule maps a pattern to a destination directory. Multiple patterns can be grouped with commas in a single key:
"rules": {
".pdf": "C:/Users/%USERNAME%/Documents/PDF",
".doc,.docx": "C:/Users/%USERNAME%/Documents/Word",
".jpg,.jpeg,.png,.gif,.bmp,.svg,.webp": "C:/Users/%USERNAME%/Pictures",
".zip,.rar,.7z,.tar,.gz": "C:/Users/%USERNAME%/Downloads/Archives",
"setup*.exe,installer*.msi": "C:/Users/%USERNAME%/Downloads/Installers"
}Supported pattern types:
| Pattern | Example | Matches |
|---|---|---|
| Exact extension | .pdf |
Any file ending in .pdf (case-insensitive) |
| Glob pattern | Screenshot* |
Screenshot 2024-01-01.png, Screenshot_new.jpg |
| Glob pattern | Report-202?-*.xlsx |
Report-2024-01.xlsx, Report-2025-12.xlsx |
| Comma-separated | .jpg,.png,.gif |
Any of the three extensions → same folder |
Matching priority:
Rules are checked in the order they appear in config.json — the first
match wins. Place specific patterns (e.g. eie-*.tar) before general ones
(e.g. .tar).
Files that match no rule are moved to unsorted_directory.
Destinations can include dynamic tokens for date-based subdirectories:
".log": "C:/Users/%USERNAME%/logs/{created:%Y-%m-%d}",
"screenshot*": "C:/Pictures/screenshots/{modified:%Y-%m}"| Token | Example value |
|---|---|
{created:%Y-%m-%d} |
2025-07-02 |
{modified:%Y-%m} |
2025-07 |
{created:%Y} |
2025 |
Uses strftime format codes. created reads st_ctime (creation time on
Windows). modified reads st_mtime.
Files matching these patterns are never processed — no logging, no move:
"ignore_patterns": [
"~$*", // Office temp files
"*.crdownload", // Chrome partial downloads
"*.tmp", // Temporary files
"*.part", // Firefox/IE partial downloads
"*.partial", // Edge partial downloads
"*.lnk", // Desktop shortcuts
"*.url", // Internet shortcuts
"desktop.ini", // System file
"Thumbs.db" // System file
]{
"watch_directories": [
"C:/Users/%USERNAME%/Desktop",
"C:/Users/%USERNAME%/Downloads"
],
"unsorted_directory": "C:/Users/%USERNAME%/Desktop/Unsorted",
"debounce_seconds": 4.0,
"log_file": "C:/Users/%USERNAME%/Desktop/file_sorter.log",
"max_log_files": 20,
"quiet": true,
"debug": false,
"sort_existing_on_start": true,
"ignore_patterns": [
"~$*",
"*.crdownload",
"*.tmp",
"*.part",
"*.partial",
"*.lnk",
"*.url",
"desktop.ini",
"Thumbs.db"
],
"rules": {
".pdf,.doc,.docx,.xls,.xlsx": "C:/Users/%USERNAME%/Documents",
".jpg,.jpeg,.png,.gif,.bmp,.svg,.webp": "C:/Users/%USERNAME%/Pictures",
".mp3,.wav,.flac": "C:/Users/%USERNAME%/Music",
".mp4,.mkv,.avi,.mov": "C:/Users/%USERNAME%/Videos",
".zip,.rar,.7z,.tar,.gz": "C:/Users/%USERNAME%/Downloads/Archives",
".exe,.msi": "C:/Users/%USERNAME%/Downloads/Installers",
".iso": "C:/Users/%USERNAME%/Downloads/ISOs",
".torrent": "C:/Users/%USERNAME%/Downloads/Torrents"
}
}| File | Purpose |
|---|---|
file_sorter.py |
Main engine — monitors folders, matches rules, moves files |
gui.py |
GUI control panel source (Tkinter) |
File Sorter Manager.exe |
Compiled GUI (built via build_exe.bat) |
config.json |
All settings and rules |
install.bat |
First-time setup: installs dependencies + creates Task Scheduler job |
uninstall.bat |
Removes the Task Scheduler job |
start.bat |
Starts the sorter in background |
stop.bat |
Stops any running sorter instance |
restart.bat |
Stops + starts the sorter |
run_silent.vbs |
VBScript launcher — starts Python without a console window |
run_debug.bat |
Starts the sorter with a visible console (for troubleshooting) |
build_exe.bat |
Builds File Sorter Manager.exe from gui.py using PyInstaller |
requirements.txt |
Python dependency: watchdog>=3.0 |
.gitignore |
Excludes auto-generated files from version control |
.runtime/ |
Auto-generated at runtime: lock file, PID file, Python path cache |
start.batOr: wscript.exe run_silent.vbs
stop.batrestart.batThe log file location is set in config.json under log_file. Each sorter
launch creates a new timestamped log file:
file_sorter-2025-07-02-14-30-05.log. Old logs are kept — the oldest ones
are cleaned up, keeping at most max_log_files (default 20).
Logs can also be viewed live in the GUI (Logs tab).
- Edit
config.json(text editor or GUI) - Run
restart.bat(or click Restart in the GUI)
The sorter reads the config fresh on every launch.
Set "debug": true in config.json to include [DEBUG] messages in log files
(every file detection, every retry attempt, etc). Toggle in the GUI via the
Debug mode checkbox.
If the sorter doesn't start after reboot:
- Run
run_debug.bat— shows the console with all error messages - Common issues: Python not in PATH, watchdog not installed, invalid config
-
File system monitoring — uses Python's
watchdoglibrary, which wraps the native WindowsReadDirectoryChangesWAPI. No polling — the OS notifies the process only when filesystem events occur. CPU usage when idle: effectively zero. -
Debouncing — when a file appears, the script waits
debounce_secondsbefore acting. Each subsequent write to the same file resets the timer. This prevents moving files that are still being downloaded or written. -
Rule matching — rules are checked in the order they appear in
config.json. First match wins. Extension patterns (starting with.) are compared to the file's extension. Glob patterns are matched viafnmatch. Place specific patterns before general ones for correct prioritization. -
Move with retry — if a file is locked by another process (antivirus, still-open handle), the script retries with exponential backoff up to 20 times (~30 sec total).
-
Name collision handling — if
report.pdfalready exists in the destination, the file is saved asreport (1).pdf,report (2).pdf, etc. -
Logging — every successful move is logged at INFO level. A new timestamped log file is created per launch. Old log files are cleaned up automatically, keeping the most recent N (configurable via
max_log_files). -
Single-instance lock — only one sorter process can run at a time. A mutex lock in
.runtime/sorter.lockprevents accidental duplicates.
When the sorter starts, it ensures all target directories from rules and
unsorted_directory exist — creating parent directories as needed. It also
creates directories on-demand when moving files, as a safety net.
- Directories — only files are ever moved
- Temporary/in-progress downloads —
*.crdownload,*.tmp,*.part,*.partial - Shortcuts —
*.lnk,*.url - System files —
desktop.ini,Thumbs.db - Office lock files —
~$* - Any pattern manually added to
ignore_patterns
| Problem | Solution |
|---|---|
| Sorter doesn't start after reboot | Run run_debug.bat to see errors. Check Task Scheduler → Desktop File Sorter → History |
| Files appear but aren't moved | Check ignore_patterns in config; check the log file |
| "ModuleNotFoundError: No module named 'watchdog'" | Run pip install -r requirements.txt as Administrator |
| "Permission denied" in logs | Target folder may require admin rights; adjust paths in config |
| Task Scheduler says "Access denied" | Run install.bat as Administrator |
| Sorter moves file too early (download not finished) | Increase debounce_seconds to 5–10 seconds |
| "Another instance is already running" | A sorter process is already active. Run stop.bat then start.bat |
Run uninstall.bat — removes the Task Scheduler job. The script files
(config, logs, Python files) are not deleted; delete the project folder
manually if needed.