Skip to main content
pyofiles logo

CI PyPI version Python ≥3.9 License

pyofiles

Fast, Rust-powered file operations for Python. Drop-in replacements for os.walk, os.listdir, and glob.glob -- built on parallel directory walkers for maximum speed.

Install

uv add pyofiles

or with pip:

pip install pyofiles

CLI

pyofiles includes a command-line interface. Run directly with uvx:

uvx pyofiles find . --ext .py --modified-after 7d

Or install globally with uv tool:

uv tool install pyofiles

Version

pyofiles --version
pyofiles -v

You can also check the version from Python:

import pyofiles
print(pyofiles.__version__)

Examples

# Walk a directory, showing only Python files
pyofiles walk ./src --ext .py --skip-hidden

# Long format: type, size, modified time, path
pyofiles walk ./src --ext .py -l

# Walk with name and size filters
pyofiles walk ./src --names main utils --min-size 0.001

# Find files by name substring
pyofiles find ./data --names report invoice --ext .pdf

# Find files modified in the last 7 days
pyofiles find ./project --ext .py --modified-after 7d

# Find files created before a specific date
pyofiles find ./logs --ext .log --created-before 2024-06-01

# Find large files modified recently
pyofiles find ./data --ext .csv --min-size 100 --modified-after 24h

# Find by size alone
pyofiles find . --min-size 500

# Stop after the first match (fast lookups in huge trees)
pyofiles find ./drawings --names P-1042 --limit 1

# Tune walker threads (more helps on network drives)
pyofiles find //server/share --ext .pdf --threads 16

# Glob pattern matching (with time/size filters)
pyofiles glob ./project "**/*.rs"
pyofiles glob ./project "**/*.py" --modified-after 7d --max-depth 3

# List directory contents (with filters)
pyofiles ls ./some/dir -l
pyofiles ls ./src --ext .py --skip-hidden

# Index files by stem (with time filters)
pyofiles index ./src --ext .py .pyi .pyc
pyofiles index ./src --ext .py --created-after 2024-01-01

# Disk usage analysis (with extension/time/name filters)
pyofiles du ./project --depth 2 --top 10
pyofiles du ./project --ext .py --modified-after 30d
pyofiles du ./project --names test --ext .py

# JSON output (works with all commands, pipe to jq)
pyofiles find ./src --ext .py --json
pyofiles du . --json | jq '.entries[:5]'

Time formats

Time arguments (--modified-after, --modified-before, --created-after, --created-before) accept:

Format Example Meaning
Relative duration 7d, 24h, 30m, 1w ago from now
ISO date 2024-03-15 midnight on that date
ISO datetime 2024-03-15T10:30:00 specific moment
Unix timestamp 1709251200 raw epoch seconds

Filter availability

All filters are available across commands where they make sense:

Filter walk find ls glob index du
--ext yes yes yes yes (required) yes
--names yes yes yes yes yes
--min/max-size yes yes yes yes yes yes
--skip-hidden yes yes yes yes yes yes
--max-depth yes yes yes yes
time filters yes yes yes yes yes yes
--limit yes
--threads yes yes yes yes yes

Python API

walk(directory, extensions=None, skip_hidden=False, max_depth=None, names=None, min_size_mb=None, max_size_mb=None, modified_after=None, modified_before=None, created_after=None, created_before=None, threads=None)

Parallel recursive directory walk. Returns list[FileEntry].

When any filter is given, only matching files are returned; directories are omitted. Without filters, files and directories are both included.

import pyofiles

# Walk everything
entries = pyofiles.walk("/path/to/dir")

# Only Python files
entries = pyofiles.walk("/path", extensions=[".py"])

# Files modified in the last 24 hours
import time
recent = pyofiles.walk("/path", modified_after=time.time() - 86400)

# Walk with name and size filters
entries = pyofiles.walk("/path", names=["test"], min_size_mb=0.01)

for e in entries:
    if e.is_file:
        print(f"{e.name} ({e.size} bytes)")

find(directory, names=None, extensions=None, min_size_mb=None, max_size_mb=None, skip_hidden=False, max_depth=None, modified_after=None, modified_before=None, created_after=None, created_before=None, limit=None, threads=None)

Search for files by name substrings, extensions, size, and time. Accepts multiple substrings -- a file matches if its name contains ANY of them (case-insensitive).

limit=N stops the search as soon as N matches are found, which makes single-file lookups in huge trees return almost immediately. Which matches are returned when the limit truncates is unspecified.

# Find files containing "report" or "invoice" in the name
results = pyofiles.find("/data", names=["report", "invoice"])

# Find large videos
results = pyofiles.find("/media", extensions=[".mp4", ".avi"], min_size_mb=100)

# Combine: name + extension + size
results = pyofiles.find("/docs", names=["2024"], extensions=[".pdf"], max_size_mb=50)

# Find recently modified Python files
results = pyofiles.find("/src", extensions=[".py"], modified_after=time.time() - 7*86400)

# Find files created in a date range
results = pyofiles.find("/logs", names=["error"],
                        created_after=1709251200, created_before=1711929600)

# Find by size alone
results = pyofiles.find("/data", min_size_mb=500)

# First match only: stops walking as soon as it is found
results = pyofiles.find("/drawings", names=["P-1042"], limit=1)

list_dir(directory, extensions=None, names=None, min_size_mb=None, max_size_mb=None, skip_hidden=False, modified_after=None, modified_before=None, created_after=None, created_before=None)

Non-recursive single-directory listing. Returns list[FileEntry] sorted by name.

entries = pyofiles.list_dir("/path")

# List only Python files, skip hidden
entries = pyofiles.list_dir("/src", extensions=[".py"], skip_hidden=True)

# List recently modified files
entries = pyofiles.list_dir("/data", modified_after=time.time() - 86400)

index(directory, extensions, skip_hidden=False, max_depth=None, names=None, min_size_mb=None, max_size_mb=None, modified_after=None, modified_before=None, created_after=None, created_before=None, threads=None)

Build a file index grouped by filename stem. Useful for finding related files with different extensions.

If two files share the same stem and extension (e.g. in different subdirectories), the lexicographically smallest full path is kept, so results are deterministic.

idx = pyofiles.index("/src", extensions=[".py", ".pyi", ".pyc"])
# {"main": {".py": "/src/main.py", ".pyc": "/src/__pycache__/main.pyc"}}

# Index only recently modified files
idx = pyofiles.index("/src", extensions=[".py"], modified_after=time.time() - 7*86400)

# Index with depth limit
idx = pyofiles.index("/project", extensions=[".py"], max_depth=3)

glob(directory, pattern, skip_hidden=False, max_depth=None, min_size_mb=None, max_size_mb=None, modified_after=None, modified_before=None, created_after=None, created_before=None, threads=None)

Parallel glob pattern matching. Returns list[str] of full paths.

Patterns with a literal directory prefix (e.g. src/**/*.py) start the walk at that directory instead of scanning the whole tree.

paths = pyofiles.glob("/project", "**/*.py")
paths = pyofiles.glob("/project", "src/**/*.{rs,toml}")

# Glob with time filter
paths = pyofiles.glob("/project", "**/*.py", modified_after=time.time() - 7*86400)

# Glob with size filter
paths = pyofiles.glob("/data", "**/*.csv", min_size_mb=10)

disk_usage(directory, depth=1, top=20, skip_hidden=False, extensions=None, names=None, min_size_mb=None, max_size_mb=None, modified_after=None, modified_before=None, created_after=None, created_before=None, threads=None)

Analyze disk space usage by directory. Returns a DiskUsage object.

usage = pyofiles.disk_usage("/home", depth=2, top=10)
print(f"Total: {usage.total_size_gb:.2f} GB across {usage.total_files} files")
for entry in usage.entries:
    print(f"  {entry.path}: {entry.size_mb:.1f} MB ({entry.file_count} files)")

# Disk usage for Python files only
usage = pyofiles.disk_usage("/project", extensions=[".py"])

# Disk usage of recently modified files
usage = pyofiles.disk_usage("/project", modified_after=time.time() - 30*86400)

# Disk usage of test files
usage = pyofiles.disk_usage("/project", names=["test"], extensions=[".py"])

Types

FileEntry

Returned by walk, find, list_dir.

Attribute Type
path str
name str
is_file bool
is_dir bool
size int
extension str
modified float or None
created float or None

Timestamps are unix epoch seconds. Use datetime.fromtimestamp(entry.modified) to convert. created may be None on Linux systems that don't support creation time.

SizeEntry

Returned inside DiskUsage.entries.

Attribute Type
path str
size int
file_count int
size_mb float
size_gb float

DiskUsage

Returned by disk_usage.

Attribute Type
entries list[SizeEntry]
total_size int
total_files int
total_size_mb float
total_size_gb float

Behavior notes

  • Hidden files: skip_hidden skips dot-prefixed names everywhere, and also files with the hidden attribute on Windows.
  • Creation time: on filesystems that do not support creation time (some Linux setups), created_after/created_before match no files. FileEntry.created is None there.
  • Unreadable metadata: when a size or time filter is active, files whose metadata cannot be read are excluded.
  • Result order: walk, find, and glob run in parallel and return results in no particular order. list_dir is sorted by name.

Performance

Every recursive operation runs on the ignore crate's parallel directory walker (the same engine ripgrep uses), with metadata taken from the directory read itself wherever the platform provides it (free on Windows). Bindings via PyO3. Typically 5-50x faster than equivalent Python code, especially on large directories and network drives. Wheels are abi3: one wheel per platform covers Python 3.9+.

License

MIT

Download files

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

Source Distribution

pyofiles-0.6.0.tar.gz (611.2 kB view details)

Uploaded Source

Built Distributions

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

pyofiles-0.6.0-cp39-abi3-win_amd64.whl (819.5 kB view details)

Uploaded CPython 3.9+Windows x86-64

pyofiles-0.6.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (871.7 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

pyofiles-0.6.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (795.8 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

pyofiles-0.6.0-cp39-abi3-macosx_11_0_arm64.whl (759.6 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

pyofiles-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl (827.5 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file pyofiles-0.6.0.tar.gz.

File metadata

  • Download URL: pyofiles-0.6.0.tar.gz
  • Upload date:
  • Size: 611.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyofiles-0.6.0.tar.gz
Algorithm Hash digest
SHA256 a16979b9cf698d9f46e3b4734e6b52ad03dacc640777771a3546cf2ae517cdc7
MD5 1a97f9f47756f51bd1eb94dd4b6af09f
BLAKE2b-256 586f506221d9170b91dceac699e5be874b4ab5c47ef96cc7b8b97f27f664dbf4

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyofiles-0.6.0.tar.gz:

Publisher: release.yml on lperezmo/pyofiles

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

File details

Details for the file pyofiles-0.6.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: pyofiles-0.6.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 819.5 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyofiles-0.6.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 0c5e88aaa059e0f0ecffdda387e6d9b02852e92e215a50759215f22064b14d83
MD5 0cd55465bb52c52f3059665e6560c0b9
BLAKE2b-256 65a0b0227a691d8e890cd74c93d8ef50f3e1d9dbba7cdaab8ba9f5cb0a27093d

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyofiles-0.6.0-cp39-abi3-win_amd64.whl:

Publisher: release.yml on lperezmo/pyofiles

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

File details

Details for the file pyofiles-0.6.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyofiles-0.6.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c64516d32c520a67e2b69ed3f67f46e7cecf2fd97aa53bb8cca73211be88f94f
MD5 f98a8b6b898d3a03f760f83ef5c4cc34
BLAKE2b-256 18694b8858e66fc4ff2e75ecf8d0641054d169c05b901306fa7ed80459fd2164

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyofiles-0.6.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on lperezmo/pyofiles

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

File details

Details for the file pyofiles-0.6.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyofiles-0.6.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 c5d880de0207d57bcf332b154ac398c6d2d3a581866cb258f49a9fa82df235cd
MD5 9e0be2212c2b64d73c4a4c802dc18384
BLAKE2b-256 5a851720c0576ec79a03f4103bbb05442010ef232656e5caa56bb7eb9c11fbf5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyofiles-0.6.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on lperezmo/pyofiles

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

File details

Details for the file pyofiles-0.6.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyofiles-0.6.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9899289ff00843fb9e263ec4853c80f0badb30475915795f80926d47c07b32b7
MD5 3db328f21d5357ba07aabb157affb900
BLAKE2b-256 8ee06a14591b1aa7e2eb520ce1ea8fbd1b822834284accd8cbbba34974da99f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyofiles-0.6.0-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on lperezmo/pyofiles

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

File details

Details for the file pyofiles-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyofiles-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b98f3a3ae207c0dff2d92d954e146feb0f991249a3474b10c4fdbe2ff53b9f81
MD5 58941de65788ed4116375f5e1a7b1be7
BLAKE2b-256 a51658ce59268b736a1fcb3ef83972995eec89211b440bafafc6ba882034230b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyofiles-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on lperezmo/pyofiles

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 Sentry Error logging StatusPage Status page