Skip to main content

Unclutter your directory with ease.

Project description

PyPI Version Python Versions Tests License

Table of Contents 📑

Unclutter Directory 🗂️

A powerful and flexible file organization tool that helps you effortlessly declutter your directories by automatically sorting files and folders according to your custom rules. Save time, stay organized, and keep your workspace neat with Unclutter Directory.

A few reasons why Unclutter Directory stands out:

  • 🚀 Automate tedious file organization tasks effortlessly
  • 🔧 Highly customizable rules to fit any workflow
  • 🛡️ Safe operations with dry-run and interactive prompts
  • 📦 Supports compression and archive content searching
  • 🗑️ Intelligent duplicate detection and cleanup
  • 🧪 Actively maintained with comprehensive testing

Features ✨

  • Multi-Action Support

    • 🚚 Move files and folders to specific locations with ease
    • 🗑️ Delete obsolete files and folders safely
    • 📦 Compress files and folders into ZIP archives effortlessly
    • 🔍 Search inside ZIP, RAR, and 7Z archives for matching files quickly
  • Unpacked Detection

    • 🔍 Automatically remove uncompressed directories matching compressed files
    • 🗂️ Compare file structures between archives and directories accurately
    • 🗑️ Interactive prompts for safe removal of uncompressed directories
  • Advanced Matching

    • Match by name patterns: starts with, ends with, contains, or regex
    • Filter by file size: larger than or smaller than specified thresholds
    • Filter by age: older than or newer than specified durations
    • Apply rules specifically to directories using the is_directory flag
    • Support for case-sensitive or insensitive matching
  • Safety & Control

    • 🧪 Dry-run mode to simulate actions without changes
    • 🔒 Interactive prompts to confirm deletions
    • 📝 Comprehensive and detailed logging for audit trails

Installation 📦

pip install unclutter-directory

Usage 🚀

Basic Command Structure

unclutter organize [OPTIONS] TARGET_DIR [RULES_FILE]
unclutter validate [OPTIONS] RULES_FILE
unclutter delete-unpacked [OPTIONS] TARGET_DIR

Common Options

Option Description
--dry-run Simulate actions without making changes
--quiet Suppress non-error messages
--include-hidden Include hidden files and directories
--always-delete Skip confirmation prompts for deletions
--never-delete Disable all deletion actions

Delete-Unpacked Specific Options:

Option Description
--dry-run Show what would be removed (default behavior)
--always-delete Remove uncompressed directories without confirmation
--never-delete Only report matches, don't remove anything
--include-hidden Include hidden files in structure comparison

Example Workflow

  1. Create a rules file (cleanup_rules.yaml):
- name: "Cleanup Old Downloads"
  conditions:
    older: "30d"
  action:
    type: delete

- name: "Organize Media Files"
  is_directory: false
  conditions:
    regex: "\.(mp4|mov|avi)$"
  action:
    type: move
    target: "media/"

- name: "Archive Projects"
  is_directory: true
  conditions:
    end: "_project"
    newer: "7d"
  action:
    type: compress
    target: "archives/"
  1. Run organization in dry-run mode to preview changes:
unclutter organize ~/Downloads cleanup_rules.yaml --dry-run
  1. Apply changes:
unclutter organize ~/Downloads cleanup_rules.yaml

Delete Unpacked Command

Remove uncompressed directories that have the same structure as compressed files:

# Find uncompressed directories in dry-run mode (default)
unclutter delete-unpacked ~/Downloads

# Always remove uncompressed directories without confirmation
unclutter delete-unpacked ~/Downloads --always-delete

# Never delete, only show what would be removed
unclutter delete-unpacked ~/Downloads --never-delete

# Include hidden files in comparison
unclutter delete-unpacked ~/Downloads --include-hidden

How it works:

  • Scans for ZIP/RAR/7Z files in the target directory
  • Looks for directories with the same name (without extension)
  • Compares file structures between archive and directory
  • Prompts for deletion if structures are identical
  • Safely handles large directories and archives

Rules Format Specification ⚙️

The rules file must be a YAML file containing a list of rule dictionaries. Each rule defines matching criteria and actions to perform on files/directories.

File Structure

The rules file must be valid YAML in this format:

---
# List of rules (at least one rule required)
- name: "Rule Name"        # Optional: Descriptive name (1-200 chars)
  description: "Optional longer description"  # Optional: Description (up to 1000 chars)

  # REQUIRED: Matching conditions (at least one condition required)
  conditions:
    # Pattern matching (strings/regex)
    start: "prefix_"        # Match files starting with pattern
    end: ".ext"             # Match files ending with pattern
    contain: "substring"    # Match files containing pattern
    regex: "^pattern.*$"    # Match files using regex pattern

    # Size conditions (value + unit)
    larger: "100MB"         # Match files larger than size
    smaller: "1GB"          # Match files smaller than size

    # Time conditions (value + unit)
    older: "30d"            # Match files older than time
    newer: "2w"             # Match files newer than time

  # REQUIRED: Action to perform
  action:
    type: "move|delete|compress"  # Action type
    target: "path/"               # Required for move/compress actions

  # OPTIONAL: Behavioral flags (boolean)
  case_sensitive: false     # Case-sensitive pattern matching (default: false)
  check_archive: false      # Search inside ZIP/RAR/7Z archives (default: false)
  is_directory: false       # Apply rule only to directories (default: false)

Rule Fields

Required Fields

  • conditions: Dictionary of matching criteria (at least one condition required)
  • action: Dictionary specifying the action to perform

Optional Fields

  • name: String (1-200 characters) - Rule identifier/description
  • description: String (up to 1000 characters) - Longer rule description
  • case_sensitive: Boolean - Whether pattern matching is case-sensitive (default: false)
  • check_archive: Boolean - Whether to search inside compressed archives (default: false)
  • is_directory: Boolean - Whether rule applies only to directories (default: false)

Condition Types

Pattern Matching Conditions

These conditions use string matching or regular expressions:

Condition Type Description Examples
start String Match files starting with pattern "temp_", "report_"
end String Match files ending with pattern ".pdf", "_backup"
contain String Match files containing pattern "draft", "2019"
regex Pattern Match files using regex pattern "^201\d{2}.*\.pdf$", "\w+\d{3}"

Size Conditions

Match files based on their size. Format: <number><unit> or just <number> (defaults to bytes).

Condition Description Unit Examples
larger Match files larger than size "500MB", "1GB", "1024KB"
smaller Match files smaller than size "100MB", "2GB", "512" (bytes)

Supported Size Units:

  • B - Bytes (default if no unit specified)
  • KB - Kilobytes (1024 bytes)
  • MB - Megabytes (1024² bytes)
  • GB - Gigabytes (1024³ bytes)

Time Conditions

Match files based on modification time. Format: <number><unit> or just <number> (defaults to seconds).

Condition Description Unit Examples
older Match files older than time "30d", "2w", "6h"
newer Match files newer than time "1d", "4h", "30m"

Supported Time Units:

  • s - Seconds (default if no unit specified)
  • m - Minutes (60 seconds)
  • h - Hours (3600 seconds)
  • d - Days (86400 seconds)
  • w - Weeks (604800 seconds)

Action Types

Available Actions

Action Type Description Requires target Example
move Move files/directories to target path ✅ Yes {"type": "move", "target": "sorted/"}
delete Delete matching files/directories ❌ No {"type": "delete"}
compress Compress files/directories into ZIP ✅ Yes {"type": "compress", "target": "archives/"}

Action Field Format

action:
  type: "move|delete|compress"        # Required: Action type
  target: "destination/path"          # Required for move/compress

Note: The target parameter:

  • Must be a string path
  • For move: destination directory (relative to working directory)
  • For compress: directory where compressed file will be created
  • Relative paths are supported (e.g., "subdir/", "../other_dir/")
  • Directory must exist (will not be auto-created)

Validation Rules

The rules file is strictly validated. Common validation errors include:

  • File Level:

    • Must be a YAML list (not a single rule object)
    • Cannot be empty (at least one rule required)
    • File must be readable and ≤10MB
  • Rule Level:

    • Each rule must be a dictionary object
    • Must contain conditions field with at least one valid condition
    • Must contain valid action field
    • Optional fields (name, description) must be strings within length limits
    • Flags (case_sensitive, check_archive, is_directory) must be boolean
  • Condition Level:

    • Condition keys must be from valid set: start, end, contain, regex, larger, smaller, older, newer
    • Values cannot be empty/null
    • Size values must follow <number><unit> format
    • Time values must follow <number><unit> format
    • Regex patterns must be valid regular expressions
  • Action Level:

    • Must be a dictionary with required type field
    • type must be one of: move, delete, compress
    • target is required for move and compress actions
    • target must be a non-empty string

Examples

Basic File Rule

- name: "Organize Office Documents"
  conditions:
    end: ".pdf"
    smaller: "50MB"
  action:
    type: move
    target: "documents/"

Directory Compression Rule

- name: "Compress Old Projects"
  is_directory: true
  conditions:
    older: "6M"
    larger: "100MB"
  action:
    type: compress
    target: "archives/"

Archive Search Rule

- name: "Find Confidential Documents"
  check_archive: true
  case_sensitive: true
  conditions:
    regex: "confidential.*\.docx$"
  action:
    type: move
    target: "classified/"

Multiple Conditions Rule

- name: "Cleanup Old Downloads"
  conditions:
    start: "temp_"
    end: ".tmp"
    older: "7d"
    larger: "10MB"
  action:
    type: delete

Advanced Usage 🔧

New Option: Automatic Deletion of Unpacked Directories

The boolean option delete_unpacked_on_match (default false) allows automatic deletion of an identical unpacked directory after a successful action (e.g., move) on a compressed file.

Example in rules.yaml:

- name: 'Move ZIP and clean'
  conditions:
    end: '.zip'
  action:
    type: 'move'
    target: 'Files/'
    delete_unpacked_on_match: true

Note: This option respects flags such as --dry-run (simulates deletion) and --always-delete (skips confirmation prompts for deletion).

Archive Handling

Search inside compressed files:

- name: "Find Secret Documents"
  check_archive: true
  conditions:
    regex: "top_secret.*\.docx$"
  action:
    type: move
    target: "classified/"

Directory Compression

- name: "Archive Old Projects"
  is_directory: true
  conditions:
    older: "6M"
  action:
    type: compress
    target: "project_archives/"

Development 👩💻

Project Setup

git clone https://github.com/zirition/unclutter-directory
cd unclutter-directory
uv sync --dev  # Install with development dependencies

Testing

uv run pytest

License 📄

MIT License

Contribute 🤝

We welcome contributions! Whether it's bug reports, feature requests, documentation improvements, or code contributions, your help is appreciated.

To contribute:

  1. Fork the repository
  2. Create a new branch for your feature or bugfix
  3. Submit a pull request with a clear description of your changes

Support 💬

Have questions, found a bug, or want to request a feature?

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unclutter_directory-1.0.0.tar.gz (68.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

unclutter_directory-1.0.0-py3-none-any.whl (51.4 kB view details)

Uploaded Python 3

File details

Details for the file unclutter_directory-1.0.0.tar.gz.

File metadata

  • Download URL: unclutter_directory-1.0.0.tar.gz
  • Upload date:
  • Size: 68.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for unclutter_directory-1.0.0.tar.gz
Algorithm Hash digest
SHA256 fa4cc4370e148b33b350d59a408bab94524713e4430d75aada3f807be7370d1c
MD5 9208917b7521ad3f4e1ae53d69279e1e
BLAKE2b-256 218866fc8ecb82dc92473ae4242cbd3886b242ed091fd1730a5024a3f58e8348

See more details on using hashes here.

Provenance

The following attestation bundles were made for unclutter_directory-1.0.0.tar.gz:

Publisher: python-publish.yml on zirition/unclutter-directory

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file unclutter_directory-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for unclutter_directory-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9df2e04a50febd2c90bd58a3725db78d203a7fc126e5e330b7ebed91a7a938ad
MD5 df5570beec2987b7b4094f4ee89259ec
BLAKE2b-256 e2b1d7e16843e02d0007a57cd620bd94c78fdb5467254e53c30002827463c0f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for unclutter_directory-1.0.0-py3-none-any.whl:

Publisher: python-publish.yml on zirition/unclutter-directory

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page