unclutter-directory


Nameunclutter-directory JSON
Version 0.9.5 PyPI version JSON
download
home_pageNone
SummaryUnclutter your directory with ease.
upload_time2025-08-30 22:48:00
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords unclutter directory organize clean files folders
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![PyPI Version](https://img.shields.io/pypi/v/unclutter-directory)](https://pypi.org/project/unclutter-directory/)
[![Python Versions](https://img.shields.io/pypi/pyversions/unclutter-directory)](https://pypi.org/project/unclutter-directory/)
[![Tests](https://github.com/zirition/unclutter-directory/workflows/Python%20package/badge.svg)](https://github.com/zirition/unclutter-directory/actions?query=workflow%3APython%20package)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)


## Table of Contents ๐Ÿ“‘

- [Features โœจ](#features-โœจ)
- [Installation ๐Ÿ“ฆ](#installation-๐Ÿ“ฆ)
- [Usage ๐Ÿš€](#usage-๐Ÿš€)
- [Rules Format Specification โš™๏ธ](#rules-format-specification-โš™๏ธ)
- [Advanced Usage ๐Ÿ”ง](#advanced-usage-๐Ÿ”ง)
- [Development ๐Ÿ‘ฉ๐Ÿ’ป](#development-๐Ÿ‘ฉ๐Ÿ’ป)
- [Testing ๐Ÿงช](#testing-๐Ÿงช)
- [License ๐Ÿ“„](#license-๐Ÿ“„)
- [Support ๐Ÿ’ฌ](#support-๐Ÿ’ฌ)

# 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 ๐Ÿ“ฆ

```bash
pip install unclutter-directory
```

## Usage ๐Ÿš€

### Basic Command Structure

```bash
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`):
```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/"
```

2. Run organization in dry-run mode to preview changes:
```bash
unclutter organize ~/Downloads cleanup_rules.yaml --dry-run
```

3. Apply changes:
```bash
unclutter organize ~/Downloads cleanup_rules.yaml
```

### Delete Unpacked Command

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

```bash
# 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:

```yaml
---
# 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

```yaml
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
```yaml
- name: "Organize Office Documents"
  conditions:
    end: ".pdf"
    smaller: "50MB"
  action:
    type: move
    target: "documents/"
```

#### Directory Compression Rule
```yaml
- name: "Compress Old Projects"
  is_directory: true
  conditions:
    older: "6M"
    larger: "100MB"
  action:
    type: compress
    target: "archives/"
```

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

#### Multiple Conditions Rule
```yaml
- name: "Cleanup Old Downloads"
  conditions:
    start: "temp_"
    end: ".tmp"
    older: "7d"
    larger: "10MB"
  action:
    type: delete
```

## Advanced Usage ๐Ÿ”ง

### Archive Handling

Search inside compressed files:

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

### Directory Compression

```yaml
- name: "Archive Old Projects"
  is_directory: true
  conditions:
    older: "6M"
  action:
    type: compress
    target: "project_archives/"
```
## Development ๐Ÿ‘ฉ๐Ÿ’ป

### Project Setup

```bash
git clone https://github.com/zirition/unclutter-directory
cd unclutter-directory
python -m venv .venv
source .venv/bin/activate  # Linux/MacOS
# .venv\Scripts\activate  # Windows

pip install -e .[dev]  # Install with development dependencies
```


## Testing

```bash
python -m unittest discover tests
```


## 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? 

- ๐Ÿž Open an issue on GitHub: [https://github.com/zirition/unclutter-directory/issues](https://github.com/zirition/unclutter-directory/issues)


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "unclutter-directory",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "unclutter, directory, organize, clean, files, folders",
    "author": null,
    "author_email": "zirition <zirition@zirition.com>",
    "download_url": "https://files.pythonhosted.org/packages/75/8a/c8b47f7f26039d294c957d3e089c9ab1e6f253ab28874e222510572ee60d/unclutter_directory-0.9.5.tar.gz",
    "platform": null,
    "description": "[![PyPI Version](https://img.shields.io/pypi/v/unclutter-directory)](https://pypi.org/project/unclutter-directory/)\n[![Python Versions](https://img.shields.io/pypi/pyversions/unclutter-directory)](https://pypi.org/project/unclutter-directory/)\n[![Tests](https://github.com/zirition/unclutter-directory/workflows/Python%20package/badge.svg)](https://github.com/zirition/unclutter-directory/actions?query=workflow%3APython%20package)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\n\n## Table of Contents \ud83d\udcd1\n\n- [Features \u2728](#features-\u2728)\n- [Installation \ud83d\udce6](#installation-\ud83d\udce6)\n- [Usage \ud83d\ude80](#usage-\ud83d\ude80)\n- [Rules Format Specification \u2699\ufe0f](#rules-format-specification-\u2699\ufe0f)\n- [Advanced Usage \ud83d\udd27](#advanced-usage-\ud83d\udd27)\n- [Development \ud83d\udc69\ud83d\udcbb](#development-\ud83d\udc69\ud83d\udcbb)\n- [Testing \ud83e\uddea](#testing-\ud83e\uddea)\n- [License \ud83d\udcc4](#license-\ud83d\udcc4)\n- [Support \ud83d\udcac](#support-\ud83d\udcac)\n\n# Unclutter Directory \ud83d\uddc2\ufe0f\n\nA 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.\n\nA few reasons why Unclutter Directory stands out:\n\n- \ud83d\ude80 Automate tedious file organization tasks effortlessly\n- \ud83d\udd27 Highly customizable rules to fit any workflow\n- \ud83d\udee1\ufe0f Safe operations with dry-run and interactive prompts\n- \ud83d\udce6 Supports compression and archive content searching\n- \ud83d\uddd1\ufe0f Intelligent duplicate detection and cleanup\n- \ud83e\uddea Actively maintained with comprehensive testing\n\n## Features \u2728\n\n- **Multi-Action Support**\n  - \ud83d\ude9a Move files and folders to specific locations with ease\n  - \ud83d\uddd1\ufe0f Delete obsolete files and folders safely\n  - \ud83d\udce6 Compress files and folders into ZIP archives effortlessly\n  - \ud83d\udd0d Search inside ZIP, RAR, and 7Z archives for matching files quickly\n\n- **Unpacked Detection**\n  - \ud83d\udd0d Automatically remove uncompressed directories matching compressed files\n  - \ud83d\uddc2\ufe0f Compare file structures between archives and directories accurately\n  - \ud83d\uddd1\ufe0f Interactive prompts for safe removal of uncompressed directories\n\n- **Advanced Matching**\n  - Match by name patterns: starts with, ends with, contains, or regex\n  - Filter by file size: larger than or smaller than specified thresholds\n  - Filter by age: older than or newer than specified durations\n  - Apply rules specifically to directories using the `is_directory` flag\n  - Support for case-sensitive or insensitive matching\n\n- **Safety & Control**\n  - \ud83e\uddea Dry-run mode to simulate actions without changes\n  - \ud83d\udd12 Interactive prompts to confirm deletions\n  - \ud83d\udcdd Comprehensive and detailed logging for audit trails\n\n## Installation \ud83d\udce6\n\n```bash\npip install unclutter-directory\n```\n\n## Usage \ud83d\ude80\n\n### Basic Command Structure\n\n```bash\nunclutter organize [OPTIONS] TARGET_DIR [RULES_FILE]\nunclutter validate [OPTIONS] RULES_FILE\nunclutter delete-unpacked [OPTIONS] TARGET_DIR\n```\n\n### Common Options\n\n| Option           | Description                             |\n|------------------|---------------------------------------|\n| --dry-run        | Simulate actions without making changes |\n| --quiet          | Suppress non-error messages             |\n| --include-hidden | Include hidden files and directories    |\n| --always-delete  | Skip confirmation prompts for deletions  |\n| --never-delete   | Disable all deletion actions             |\n\n**Delete-Unpacked Specific Options:**\n\n| Option           | Description                                   |\n|------------------|-----------------------------------------------|\n| --dry-run        | Show what would be removed (default behavior) |\n| --always-delete  | Remove uncompressed directories without confirmation |\n| --never-delete   | Only report matches, don't remove anything    |\n| --include-hidden | Include hidden files in structure comparison  |\n\n### Example Workflow\n\n1. Create a rules file (`cleanup_rules.yaml`):\n```yaml\n- name: \"Cleanup Old Downloads\"\n  conditions:\n    older: \"30d\"\n  action:\n    type: delete\n\n- name: \"Organize Media Files\"\n  is_directory: false\n  conditions:\n    regex: \"\\.(mp4|mov|avi)$\"\n  action:\n    type: move\n    target: \"media/\"\n\n- name: \"Archive Projects\"\n  is_directory: true\n  conditions:\n    end: \"_project\"\n    newer: \"7d\"\n  action:\n    type: compress\n    target: \"archives/\"\n```\n\n2. Run organization in dry-run mode to preview changes:\n```bash\nunclutter organize ~/Downloads cleanup_rules.yaml --dry-run\n```\n\n3. Apply changes:\n```bash\nunclutter organize ~/Downloads cleanup_rules.yaml\n```\n\n### Delete Unpacked Command\n\nRemove uncompressed directories that have the same structure as compressed files:\n\n```bash\n# Find uncompressed directories in dry-run mode (default)\nunclutter delete-unpacked ~/Downloads\n\n# Always remove uncompressed directories without confirmation\nunclutter delete-unpacked ~/Downloads --always-delete\n\n# Never delete, only show what would be removed\nunclutter delete-unpacked ~/Downloads --never-delete\n\n# Include hidden files in comparison\nunclutter delete-unpacked ~/Downloads --include-hidden\n```\n\n**How it works:**\n- Scans for ZIP/RAR/7Z files in the target directory\n- Looks for directories with the same name (without extension)\n- Compares file structures between archive and directory\n- Prompts for deletion if structures are identical\n- Safely handles large directories and archives\n\n## Rules Format Specification \u2699\ufe0f\n\nThe 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.\n\n### File Structure\n\nThe rules file must be valid YAML in this format:\n\n```yaml\n---\n# List of rules (at least one rule required)\n- name: \"Rule Name\"        # Optional: Descriptive name (1-200 chars)\n  description: \"Optional longer description\"  # Optional: Description (up to 1000 chars)\n\n  # REQUIRED: Matching conditions (at least one condition required)\n  conditions:\n    # Pattern matching (strings/regex)\n    start: \"prefix_\"        # Match files starting with pattern\n    end: \".ext\"             # Match files ending with pattern\n    contain: \"substring\"    # Match files containing pattern\n    regex: \"^pattern.*$\"    # Match files using regex pattern\n\n    # Size conditions (value + unit)\n    larger: \"100MB\"         # Match files larger than size\n    smaller: \"1GB\"          # Match files smaller than size\n\n    # Time conditions (value + unit)\n    older: \"30d\"            # Match files older than time\n    newer: \"2w\"             # Match files newer than time\n\n  # REQUIRED: Action to perform\n  action:\n    type: \"move|delete|compress\"  # Action type\n    target: \"path/\"               # Required for move/compress actions\n\n  # OPTIONAL: Behavioral flags (boolean)\n  case_sensitive: false     # Case-sensitive pattern matching (default: false)\n  check_archive: false      # Search inside ZIP/RAR/7Z archives (default: false)\n  is_directory: false       # Apply rule only to directories (default: false)\n```\n\n### Rule Fields\n\n#### Required Fields\n- **`conditions`**: Dictionary of matching criteria (at least one condition required)\n- **`action`**: Dictionary specifying the action to perform\n\n#### Optional Fields\n- **`name`**: String (1-200 characters) - Rule identifier/description\n- **`description`**: String (up to 1000 characters) - Longer rule description\n- **`case_sensitive`**: Boolean - Whether pattern matching is case-sensitive (default: `false`)\n- **`check_archive`**: Boolean - Whether to search inside compressed archives (default: `false`)\n- **`is_directory`**: Boolean - Whether rule applies only to directories (default: `false`)\n\n### Condition Types\n\n#### Pattern Matching Conditions\nThese conditions use string matching or regular expressions:\n\n| Condition | Type     | Description | Examples |\n|-----------|----------|-------------|----------|\n| `start`   | String   | Match files starting with pattern | `\"temp_\"`, `\"report_\"` |\n| `end`     | String   | Match files ending with pattern | `\".pdf\"`, `\"_backup\"` |\n| `contain` | String   | Match files containing pattern | `\"draft\"`, `\"2019\"` |\n| `regex`   | Pattern  | Match files using regex pattern | `\"^201\\d{2}.*\\.pdf$\"`, `\"\\w+\\d{3}\"` |\n\n#### Size Conditions\nMatch files based on their size. Format: `<number><unit>` or just `<number>` (defaults to bytes).\n\n| Condition | Description | Unit Examples |\n|-----------|-------------|---------------|\n| `larger`  | Match files larger than size | `\"500MB\"`, `\"1GB\"`, `\"1024KB\"` |\n| `smaller` | Match files smaller than size | `\"100MB\"`, `\"2GB\"`, `\"512\"` (bytes) |\n\n**Supported Size Units:**\n- `B` - Bytes (default if no unit specified)\n- `KB` - Kilobytes (1024 bytes)\n- `MB` - Megabytes (1024\u00b2 bytes)\n- `GB` - Gigabytes (1024\u00b3 bytes)\n\n#### Time Conditions\nMatch files based on modification time. Format: `<number><unit>` or just `<number>` (defaults to seconds).\n\n| Condition | Description | Unit Examples |\n|-----------|-------------|---------------|\n| `older`   | Match files older than time | `\"30d\"`, `\"2w\"`, `\"6h\"` |\n| `newer`   | Match files newer than time | `\"1d\"`, `\"4h\"`, `\"30m\"` |\n\n**Supported Time Units:**\n- `s` - Seconds (default if no unit specified)\n- `m` - Minutes (60 seconds)\n- `h` - Hours (3600 seconds)\n- `d` - Days (86400 seconds)\n- `w` - Weeks (604800 seconds)\n\n### Action Types\n\n#### Available Actions\n\n| Action Type | Description | Requires `target` | Example |\n|------------|-------------|-------------------|---------|\n| `move`     | Move files/directories to target path | \u2705 Yes | `{\"type\": \"move\", \"target\": \"sorted/\"}` |\n| `delete`   | Delete matching files/directories | \u274c No | `{\"type\": \"delete\"}` |\n| `compress` | Compress files/directories into ZIP | \u2705 Yes | `{\"type\": \"compress\", \"target\": \"archives/\"}` |\n\n#### Action Field Format\n\n```yaml\naction:\n  type: \"move|delete|compress\"        # Required: Action type\n  target: \"destination/path\"          # Required for move/compress\n```\n\n**Note:** The `target` parameter:\n- Must be a string path\n- For `move`: destination directory (relative to working directory)\n- For `compress`: directory where compressed file will be created\n- Relative paths are supported (e.g., `\"subdir/\"`, `\"../other_dir/\"`)\n- Directory must exist (will not be auto-created)\n\n### Validation Rules\n\nThe rules file is strictly validated. Common validation errors include:\n\n- **File Level:**\n  - Must be a YAML list (not a single rule object)\n  - Cannot be empty (at least one rule required)\n  - File must be readable and \u226410MB\n\n- **Rule Level:**\n  - Each rule must be a dictionary object\n  - Must contain `conditions` field with at least one valid condition\n  - Must contain valid `action` field\n  - Optional fields (`name`, `description`) must be strings within length limits\n  - Flags (`case_sensitive`, `check_archive`, `is_directory`) must be boolean\n\n- **Condition Level:**\n  - Condition keys must be from valid set: `start`, `end`, `contain`, `regex`, `larger`, `smaller`, `older`, `newer`\n  - Values cannot be empty/null\n  - Size values must follow `<number><unit>` format\n  - Time values must follow `<number><unit>` format\n  - Regex patterns must be valid regular expressions\n\n- **Action Level:**\n  - Must be a dictionary with required `type` field\n  - `type` must be one of: `move`, `delete`, `compress`\n  - `target` is required for `move` and `compress` actions\n  - `target` must be a non-empty string\n\n### Examples\n\n#### Basic File Rule\n```yaml\n- name: \"Organize Office Documents\"\n  conditions:\n    end: \".pdf\"\n    smaller: \"50MB\"\n  action:\n    type: move\n    target: \"documents/\"\n```\n\n#### Directory Compression Rule\n```yaml\n- name: \"Compress Old Projects\"\n  is_directory: true\n  conditions:\n    older: \"6M\"\n    larger: \"100MB\"\n  action:\n    type: compress\n    target: \"archives/\"\n```\n\n#### Archive Search Rule\n```yaml\n- name: \"Find Confidential Documents\"\n  check_archive: true\n  case_sensitive: true\n  conditions:\n    regex: \"confidential.*\\.docx$\"\n  action:\n    type: move\n    target: \"classified/\"\n```\n\n#### Multiple Conditions Rule\n```yaml\n- name: \"Cleanup Old Downloads\"\n  conditions:\n    start: \"temp_\"\n    end: \".tmp\"\n    older: \"7d\"\n    larger: \"10MB\"\n  action:\n    type: delete\n```\n\n## Advanced Usage \ud83d\udd27\n\n### Archive Handling\n\nSearch inside compressed files:\n\n```yaml\n- name: \"Find Secret Documents\"\n  check_archive: true\n  conditions:\n    regex: \"top_secret.*\\.docx$\"\n  action:\n    type: move\n    target: \"classified/\"\n```\n\n### Directory Compression\n\n```yaml\n- name: \"Archive Old Projects\"\n  is_directory: true\n  conditions:\n    older: \"6M\"\n  action:\n    type: compress\n    target: \"project_archives/\"\n```\n## Development \ud83d\udc69\ud83d\udcbb\n\n### Project Setup\n\n```bash\ngit clone https://github.com/zirition/unclutter-directory\ncd unclutter-directory\npython -m venv .venv\nsource .venv/bin/activate  # Linux/MacOS\n# .venv\\Scripts\\activate  # Windows\n\npip install -e .[dev]  # Install with development dependencies\n```\n\n\n## Testing\n\n```bash\npython -m unittest discover tests\n```\n\n\n## License \ud83d\udcc4\n\nMIT License\n\n## Contribute \ud83e\udd1d\n\nWe welcome contributions! Whether it's bug reports, feature requests, documentation improvements, or code contributions, your help is appreciated.\n\nTo contribute:\n\n1. Fork the repository\n2. Create a new branch for your feature or bugfix\n3. Submit a pull request with a clear description of your changes\n\n---\n\n## Support \ud83d\udcac\n\nHave questions, found a bug, or want to request a feature? \n\n- \ud83d\udc1e Open an issue on GitHub: [https://github.com/zirition/unclutter-directory/issues](https://github.com/zirition/unclutter-directory/issues)\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Unclutter your directory with ease.",
    "version": "0.9.5",
    "project_urls": {
        "Homepage": "https://github.com/zirition/unclutter-directory",
        "Issues": "https://github.com/zirition/unclutter-directory/issues"
    },
    "split_keywords": [
        "unclutter",
        " directory",
        " organize",
        " clean",
        " files",
        " folders"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7475bbb07c569475b335172eb39e43fd963da70dc2522b8cad7ca83294d95d4b",
                "md5": "fd8e2de14d5b2114a0665aedbfd1aa85",
                "sha256": "8c116133cc394ec74ecee1a12a1621b2b12bfe19ef3e62ab82dd263e70a7c982"
            },
            "downloads": -1,
            "filename": "unclutter_directory-0.9.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "fd8e2de14d5b2114a0665aedbfd1aa85",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 48461,
            "upload_time": "2025-08-30T22:47:59",
            "upload_time_iso_8601": "2025-08-30T22:47:59.090975Z",
            "url": "https://files.pythonhosted.org/packages/74/75/bbb07c569475b335172eb39e43fd963da70dc2522b8cad7ca83294d95d4b/unclutter_directory-0.9.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "758ac8b47f7f26039d294c957d3e089c9ab1e6f253ab28874e222510572ee60d",
                "md5": "f2e454774cf6eeaf4b677ccaf4a2c99b",
                "sha256": "4a9bf2c0f87d3e15b418138fac5995c97767075c78608f869cefd64b4073e98c"
            },
            "downloads": -1,
            "filename": "unclutter_directory-0.9.5.tar.gz",
            "has_sig": false,
            "md5_digest": "f2e454774cf6eeaf4b677ccaf4a2c99b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 60106,
            "upload_time": "2025-08-30T22:48:00",
            "upload_time_iso_8601": "2025-08-30T22:48:00.514073Z",
            "url": "https://files.pythonhosted.org/packages/75/8a/c8b47f7f26039d294c957d3e089c9ab1e6f253ab28874e222510572ee60d/unclutter_directory-0.9.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-30 22:48:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "zirition",
    "github_project": "unclutter-directory",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "unclutter-directory"
}
        
Elapsed time: 0.87060s