Skip to content

pyrfs

Pythonic filesystem ergonomics, inspired by R's fs.

Tidy paths, typed self-describing values, explicit failure — chainable, and pandas-native. Pure Python ≥ 3.10, zero hard dependencies.

import pyrfs as fs

fs.dir_ls("src", recurse=True, glob="*.py")   # [FsPath('src/app.py'), ...]
fs.file_size("data.csv") > "10MB"             # True — sizes compare to literals
fs.file_copy("a.txt", "backup/")              # FsPath('backup/a.txt'), refuses to clobber

Install

Not yet on PyPI — install from GitHub:

pip install "pyrfs @ git+https://github.com/Lightbridge-KS/pyrfs"
# with the pandas integration:
pip install "pyrfs[pandas] @ git+https://github.com/Lightbridge-KS/pyrfs"

One engine, three surfaces

Every operation is implemented once and reachable three ways — pick per task, mix freely:

import pyrfs as fs

fs.path("foo", "bar", "a", ext="txt")    # FsPath('foo/bar/a.txt')
fs.dir_ls("data", glob="*.csv")
fs.file_copy("a.txt", "b.txt")           # -> FsPath('b.txt')

Closest to R's fs — the noun_verb names transfer directly. See Coming from R's fs.

from pyrfs import FsPath

(FsPath("data") / "raw.csv").with_ext("parquet").copy_to("clean/")
FsPath("project").mkdir().touch_file("README.md")
FsPath("logs").ls(glob="*.log")

FsPath is a str — it drops into open(), pd.read_csv(), any API that takes a path.

import pyrfs as fs

(fs.dir_info("src", recurse=True)
   .query("size > '10KB' and type == 'file'")   # typed columns!
   .sort_values("size", ascending=False))

df["path"].fs.ext()        # vectorized over a column

size and permissions are real ExtensionDtypes — string literals work inside .query().

Where next