Metadata-Version: 2.4
Name: philiprehberger-file-organizer
Version: 0.1.4
Summary: Rule-based file sorting engine with pattern matching and dry run support
Project-URL: Homepage, https://github.com/philiprehberger/py-file-organizer#readme
Project-URL: Repository, https://github.com/philiprehberger/py-file-organizer
Project-URL: Issues, https://github.com/philiprehberger/py-file-organizer/issues
Project-URL: Changelog, https://github.com/philiprehberger/py-file-organizer/blob/main/CHANGELOG.md
Author: Philip Rehberger
License-Expression: MIT
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# philiprehberger-file-organizer

[![Tests](https://github.com/philiprehberger/py-file-organizer/actions/workflows/publish.yml/badge.svg)](https://github.com/philiprehberger/py-file-organizer/actions/workflows/publish.yml)
[![PyPI version](https://img.shields.io/pypi/v/philiprehberger-file-organizer.svg)](https://pypi.org/project/philiprehberger-file-organizer/)
[![License](https://img.shields.io/github/license/philiprehberger/py-file-organizer)](LICENSE)

Rule-based file sorting engine with pattern matching and dry run support.

## Install

```bash
pip install philiprehberger-file-organizer
```

## Usage

```python
from philiprehberger_file_organizer import Organizer, Rule

organizer = Organizer(
    rules=[
        Rule(extensions=[".pdf", ".doc", ".docx"], destination="~/Documents"),
        Rule(extensions=[".jpg", ".png", ".gif"], destination="~/Pictures"),
        Rule(extensions=[".mp4", ".mkv"], destination="~/Videos"),
        Rule(pattern="invoice_*", destination="~/Documents/Invoices"),
    ]
)

# Preview what would happen (dry run)
report = organizer.preview("~/Downloads")
for action in report.actions:
    print(f"{action.source} -> {action.destination}")

# Execute
report = organizer.organize("~/Downloads")
print(f"Moved {report.total_moved} files ({report.total_size} bytes)")

# Undo
restored = Organizer.undo("~/Downloads")
```

## Rule Options

| Option | Description |
|--------|-------------|
| `extensions` | Match by file extension |
| `pattern` | Match by glob pattern |
| `name_contains` | Match if filename contains string |
| `larger_than` | Minimum file size in bytes |
| `smaller_than` | Maximum file size in bytes |
| `older_than_days` | Match files older than N days |
| `newer_than_days` | Match files newer than N days |
| `predicate` | Custom matching function |

## Conflict Resolution

```python
organizer = Organizer(rules=rules, conflict="rename")   # default: adds (1), (2)...
organizer = Organizer(rules=rules, conflict="skip")      # skip existing
organizer = Organizer(rules=rules, conflict="overwrite")  # overwrite existing
```


## Development

```bash
pip install -e .
python -m pytest tests/ -v
```

## License

MIT
