A Python script to automate your file organization with a powerful rules engine.
- General Info
- Key Features (v3.0)
- Technologies
- Prerequisites
- Setup
- Usage
- Settings (v3.0)
- Future Features
This project is a Python script to automate the cleaning of your Downloads folder (or any other folder). In my daily life, I download a lot of files and my Downloads folder is always a mess, so I decided to start this project.
This is not just a simple script; it's a powerful automation tool with customizable features:
- Define sorting rules for files based on extension or regex.
- New in v3.0: Define powerful rules for folders based on
globorregexpatterns. - New in v3.0: Set custom lifecycle policies (delete or trash after X days) on a per-rule basis.
- New in v3.0: Disable lifecycles for specific rules (e.g., keep movies forever).
- Set a maximum file size to ignore large files.
- Get desktop notifications when files are organized or cleaned up.
Version 3.0 introduces a complete rules engine for folders. While file rules move individual files, folder rules act on the folders themselves.
- Match By: Use simple
globpatterns (Project_*) or complexregex(.*S\d{2}E\d{2}.*). - Actions:
move_folder: Moves the entire folder (and its contents) to a new directory. Perfect for movies, series, or project backups.process_contents: Dives into the folder, moves all files to a specified directory, and then optionally deletes the now-empty source folder.ignore: Skips the folder entirely (e.g., fornode_modules).
The global daysToKeep setting is gone. Now, you have fine-grained control over how long to keep items:
defaultLifecycle: Set a default policy for any file or folder that doesn't have a specific rule.- Override Per Rule: Add an optional
lifecycleblock to any file rule (sortingRules) or folder rule (folderRules) to give it a custom expiration. - Disable Policy: Keep items forever by adding
"lifecycle": { "enabled": false }to the rule.
The entire settings.json file is now loaded and validated by Pydantic. This provides:
- Robust Error Handling: The script will fail on launch with a clear error message if your
settings.jsonis misconfigured. - Automatic
camelCase: You can keep usingcamelCase(likesourcePath) in your JSON, and it will be automatically mapped tosnake_case(likesource_path) in Python.
- Python 3.x
- Pydantic - For robust data validation and settings management.
- Send2Trash - For safely sending files to the system's trash bin.
- Plyer - For cross-platform desktop notifications.
- Python 3.x
- pip
-
Clone the repository:
git clone https://github.com/LimbersMay/AutomateDownloadsFolder.git
-
Navigate to the project directory:
cd AutomateDownloadsFolder -
Create a virtual environment (recommended):
python -m venv venv
-
Activate the virtual environment (Linux/macOS):
source venv/bin/activateActivate the virtual environment (Windows):
venv\Scripts\activate
-
Install the requirements:
pip install -r requirements.txt
-
Rename the
settings.example.jsonfile tosettings.jsonin thedatafolder and configure it (see Settings below).
You can run the script manually, create a cron job, or start the script on boot.
python main.py-
Install PyInstaller:
pip install pyinstaller
-
Create the executable:
pyinstaller --noconfirm --onefile --windowed --icon "./assets/work.ico" --hidden-import "plyer.platforms.win.notification" "./main.py"
-
Move the
.exefile from thedistfolder to the root folder. -
Press
Win + Rand typeshell:startupto open the startup folder. -
Create a shortcut to the
.exeand paste it into the startup folder. -
Restart your computer.
-
Create a new systemd user service file:
nano ~/.config/systemd/user/automate_downloads.service -
Paste the following configuration, updating the paths to match your system (especially
ExecStartandWorkingDirectory):[Unit] Description=Automate Downloads Folder Script After=network.target [Service] Type=simple # IMPORTANT: Use the Python executable INSIDE your venv ExecStart=/home/YOUR_USER/projects/AutomateDownloadsFolder/venv/bin/python /home/YOUR_USER/projects/AutomateDownloadsFolder/main.py WorkingDirectory=/home/YOUR_USER/projects/AutomateDownloadsFolder Restart=on-failure [Install] WantedBy=default.target
-
Reload the systemd daemon, enable, and start the service:
systemctl --user daemon-reload systemctl --user enable automate_downloads.service systemctl --user start automate_downloads.service
The settings are defined in data/settings.example.json. The structure has been updated for v3.0.
{
"settings": {
"maxSizeInMb": 5000
},
"defaultLifecycle": {
"enabled": true,
"action": "trash",
"daysToKeep": 7
},
"paths": {
"sourcePath": "C:\\Users\\YourUser\\Downloads",
"destinationPath": "C:\\Users\\YourUser\\Downloads\\Organized"
},
"sortingRules": [
{
"folderName": "PDF",
"matchBy": "extension",
"patterns": [".pdf"]
}
],
"defaultFolder": "Other",
"folderRules": [
{
"ruleName": "Move Series (SxxExx)",
"matchBy": "regex",
"patterns": [".*S\\d{2}E\\d{2}.*"],
"action": "move_folder",
"destinationFolder": "Videos/Series",
"lifecycle": {
"enabled": false
}
},
{
"ruleName": "Process Project Files",
"matchBy": "glob",
"patterns": ["Project_*"],
"action": "process_contents",
"destinationFolder": "School/Projects",
"deleteEmptyAfterProcessing": true,
"lifecycle": {
"enabled": true,
"action": "trash",
"daysToKeep": 30
}
},
{
"ruleName": "Ignore System Folders",
"matchBy": "glob",
"patterns": ["node_modules", ".git"],
"action": "ignore"
}
],
"defaultFolderAction": "ignore",
"orderedFiles": []
}settings: Global script settings.maxSizeInMb: Files larger than this (in MB) will be ignored by the file sorter.
defaultLifecycle: The fallback policy for any file or folder that doesn't have a customlifecycleblock in its rule.enabled:trueorfalse.action:trash(sends to system trash) ordelete(permanent deletion).daysToKeep: Number of days to keep an item before the action is applied.
paths: Core directories.sourcePath: The folder to scan (e.g., your Downloads folder).destinationPath: The root folder where organized files/folders will be moved.
sortingRules(For Files): A list of rules for individual files.folderName: The subfolder indestinationPathto move files to (e.g., "PDF").matchBy:extensionorregex.patterns: A list of patterns to match (e.g.,[".pdf"]or[".*Gemini.*"]).lifecycle(Optional): A policy block (seedefaultLifecycle) to override the default for this rule.
defaultFolder: The folder name for files that don't match anysortingRules.folderRules(For Folders): A list of rules for folders found insourcePath. Rules are processed in order.ruleName: A unique name for this rule (e.g., "Move Series"). This name is used for logging.matchBy:glob(for simple patterns likeProject_*) orregex(for complex patterns).patterns: A list of patterns to match.action:move_folder: Moves the entire folder todestinationFolder.process_contents: Moves the folder's contents todestinationFolder.ignore: Skips this folder.
destinationFolder(Optional): The subfolder indestinationPathto use formove_folderorprocess_contents.deleteEmptyAfterProcessing(Optional): Iftrue, deletes the original folder afterprocess_contentsis complete.lifecycle(Optional): A policy block to apply to the item.
defaultFolderAction: The action (move_folder,process_contents,ignore) to apply to any folder that doesn't match a rule infolderRules.ignoreis recommended for safety.orderedFiles: The audit log. This is managed by the script.rule_name_applied: The "tag" that links an item to itslifecyclepolicy.
- Support for multiple source folders.
- Support for multiple destination folders.
- Migrate data persistence from JSON to SQLite. (This is made easier by the Repository Pattern already in place—just need to create a new repository implementation).