Metadata-Version: 2.4
Name: pyfileops
Version: 1.0.0
Summary: A simple, friendly Python library for file and directory operations.
License: MIT License
        
        Copyright (c) 2026 pyfileops contributors
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/FefinDev/pyfileops
Project-URL: Issues, https://github.com/FefinDev/pyfileops/issues
Keywords: files,filesystem,copy,move,zip,utilities
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Filesystems
Classifier: Topic :: Utilities
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# pyfileops

**pyfileops** is a simple, friendly Python library for everyday file and directory operations.  
No need to juggle `os`, `shutil`, `pathlib`, or `zipfile` — everything lives behind one clean object: `fs`.

```python
from pyfileops import fs

fs.copy("report.pdf", "backup/")
fs.delete("temp.log")
print(fs.size("video.mp4"))
```

[![PyPI version](https://img.shields.io/pypi/v/pyfileops)](https://pypi.org/project/pyfileops/)
[![Python](https://img.shields.io/pypi/pyversions/pyfileops)](https://pypi.org/project/pyfileops/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

---

## Installation

```bash
pip install pyfileops
```

Requires **Python 3.8+**. No external dependencies — only the standard library.

---

## Quickstart

```python
from pyfileops import fs

# ── Files ──────────────────────────────────────────────────────────────
fs.copy("notes.txt", "backup/")           # copy into an existing folder
fs.copy("notes.txt", "backup/notes2.txt") # copy with a new name
fs.cut("draft.docx", "archive/")          # move file
fs.rename("old.txt", "new.txt")           # rename in place
fs.delete("trash.log")                    # delete a file

# ── Directories ────────────────────────────────────────────────────────
fs.mkdir("project/src/utils")             # create (nested) directories
fs.rmdir("tmp")                           # remove directory and contents

# ── Compression ────────────────────────────────────────────────────────
fs.zip("project", "project_v1.zip")       # zip a directory
fs.zip("report.pdf", "report.zip")        # zip a single file
fs.unzip("project_v1.zip", "restored/")   # extract a zip

# ── Queries ────────────────────────────────────────────────────────────
fs.exists("config.ini")    # True or False
fs.size("video.mp4")       # size in bytes (int)
fs.is_file("data.csv")     # True or False
fs.is_dir("assets")        # True or False
```

---

## API Reference

### File Operations

#### `fs.copy(source, destination) → Path`

Copies a file **or** directory to `destination`.

- If `destination` is an **existing directory**, the source is placed inside it.
- If `destination` does **not** exist, it becomes the new file/folder name.
- Missing intermediate directories are created automatically.

```python
fs.copy("logo.png", "assets/")          # → assets/logo.png
fs.copy("logo.png", "assets/icon.png")  # → assets/icon.png
fs.copy("src/", "src_backup/")          # copies whole directory tree
```

---

#### `fs.cut(source, destination) → Path`

Moves a file or directory to `destination` (copy + delete original).

```python
fs.cut("uploads/photo.jpg", "gallery/")
```

---

#### `fs.rename(path, new_name) → Path`

Renames a file or directory **in place** (same parent directory).  
To move to a different location, use `cut()`.

```python
fs.rename("report_draft.pdf", "report_final.pdf")
```

---

#### `fs.delete(path) → None`

Deletes a file or an entire directory tree.

```python
fs.delete("temp.log")    # file
fs.delete("cache/")      # directory and all its contents
```

---

### Directory Operations

#### `fs.mkdir(path) → Path`

Creates a directory (and any missing parent directories). Safe to call even if it already exists.

```python
fs.mkdir("project/assets/images")
```

---

#### `fs.rmdir(path) → None`

Removes a directory and everything inside it.

```python
fs.rmdir("build/")
```

---

### Compression

#### `fs.zip(source, zip_file) → Path`

Compresses `source` (file or directory) into a ZIP archive at `zip_file`.

```python
fs.zip("my_project", "my_project.zip")
fs.zip("data.csv", "data.zip")
```

---

#### `fs.unzip(zip_file, destination) → Path`

Extracts a ZIP archive into `destination`.

```python
fs.unzip("my_project.zip", "restored/")
```

---

### Queries

#### `fs.exists(path) → bool`

Returns `True` if `path` exists (file or directory).

```python
if fs.exists("config.ini"):
    print("Config found!")
```

---

#### `fs.size(path) → int`

Returns the size in **bytes**.

- For files: the file size.
- For directories: the total size of all contained files.

```python
bytes_used = fs.size("video.mp4")
print(f"{bytes_used / 1_000_000:.2f} MB")
```

---

#### `fs.is_file(path) → bool`

Returns `True` if `path` is a regular file (returns `False` if it doesn't exist).

```python
fs.is_file("README.md")  # True
fs.is_file("src/")       # False
```

---

#### `fs.is_dir(path) → bool`

Returns `True` if `path` is a directory (returns `False` if it doesn't exist).

```python
fs.is_dir("src/")        # True
fs.is_dir("README.md")   # False
```

---

## Error Handling

pyfileops raises clear, specific exceptions so you always know what went wrong.

| Exception | When it's raised |
|---|---|
| `FileOpsError` | Base class for all pyfileops errors |
| `PathNotFoundError` | Source path does not exist |
| `CopyError` | A copy or move operation failed |
| `DeleteError` | A delete operation failed |
| `ZipError` | A zip or unzip operation failed |

All exceptions inherit from `FileOpsError`, which inherits from `Exception`.

```python
from pyfileops import fs
from pyfileops import PathNotFoundError, CopyError, ZipError, FileOpsError

# Catch a specific error
try:
    fs.copy("missing.txt", "backup/")
except PathNotFoundError as e:
    print(e)  # Path not found: 'missing.txt'

# Catch any pyfileops error
try:
    fs.zip("project", "output.zip")
    fs.delete("tmp/")
except FileOpsError as e:
    print(f"Operation failed: {e}")
```

---

## Author

Made by [Fede](https://github.com/FefinDev) · [github.com/FefinDev/pyfileops](https://github.com/FefinDev/pyfileops)

---

## License

[MIT](LICENSE)
