Skip to content

LimbersMay/AutomateDownloadsFolder

Repository files navigation

AutomateDownloadsFolder

GitHub release (latest by date)

A Python script to automate your file organization with a powerful rules engine.

Table of contents

General Info

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 glob or regex patterns.
  • 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.

Key Features (v3.0)

🚀 Folder Rules Engine

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 glob patterns (Project_*) or complex regex (.*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., for node_modules).

⏱️ Per-Rule Lifecycles

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 lifecycle block 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.

🏗️ Pydantic Validation

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.json is misconfigured.
  • Automatic camelCase: You can keep using camelCase (like sourcePath) in your JSON, and it will be automatically mapped to snake_case (like source_path) in Python.

Technologies

  • 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.

Prerequisites

  • Python 3.x
  • pip

Setup

  1. Clone the repository:

    git clone https://github.com/LimbersMay/AutomateDownloadsFolder.git
  2. Navigate to the project directory:

    cd AutomateDownloadsFolder
  3. Create a virtual environment (recommended):

    python -m venv venv
  4. Activate the virtual environment (Linux/macOS):

    source venv/bin/activate

    Activate the virtual environment (Windows):

    venv\Scripts\activate
  5. Install the requirements:

    pip install -r requirements.txt
  6. Rename the settings.example.json file to settings.json in the data folder and configure it (see Settings below).

Usage

You can run the script manually, create a cron job, or start the script on boot.

Run Manually

python main.py

Autorun on Windows (via .exe)

  1. Install PyInstaller:

    pip install pyinstaller
  2. Create the executable:

    pyinstaller --noconfirm --onefile --windowed --icon "./assets/work.ico" --hidden-import "plyer.platforms.win.notification"  "./main.py"
  3. Move the .exe file from the dist folder to the root folder.

  4. Press Win + R and type shell:startup to open the startup folder.

  5. Create a shortcut to the .exe and paste it into the startup folder.

  6. Restart your computer.

Autorun on Linux (via systemd)

  1. Create a new systemd user service file:

    nano ~/.config/systemd/user/automate_downloads.service
  2. Paste the following configuration, updating the paths to match your system (especially ExecStart and WorkingDirectory):

    [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
  3. 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

Settings (v3.0)

The settings are defined in data/settings.example.json. The structure has been updated for v3.0.

Example settings.example.json

{
  "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 Explained

  • 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 custom lifecycle block in its rule.
    • enabled: true or false.
    • action: trash (sends to system trash) or delete (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 in destinationPath to move files to (e.g., "PDF").
    • matchBy: extension or regex.
    • patterns: A list of patterns to match (e.g., [".pdf"] or [".*Gemini.*"]).
    • lifecycle (Optional): A policy block (see defaultLifecycle) to override the default for this rule.
  • defaultFolder: The folder name for files that don't match any sortingRules.
  • folderRules (For Folders): A list of rules for folders found in sourcePath. 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 like Project_*) or regex (for complex patterns).
    • patterns: A list of patterns to match.
    • action:
      • move_folder: Moves the entire folder to destinationFolder.
      • process_contents: Moves the folder's contents to destinationFolder.
      • ignore: Skips this folder.
    • destinationFolder (Optional): The subfolder in destinationPath to use for move_folder or process_contents.
    • deleteEmptyAfterProcessing (Optional): If true, deletes the original folder after process_contents is 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 in folderRules. ignore is recommended for safety.
  • orderedFiles: The audit log. This is managed by the script.
    • rule_name_applied: The "tag" that links an item to its lifecycle policy.

Future Features

  • 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).