Skip to content

FsPath

pyrfs.FsPath

Bases: str

A tidy filesystem path string — the fluent pyrfs surface.

Construction normalizes the path (/ separators, no doubled or trailing slashes). The / operator joins; methods chain because each returns an FsPath. Inherited str behavior is untouched — p.split("/"), p.startswith(...), open(p) all work as on any string (the split-into-components method is parts, so str.split is never shadowed). In a capable terminal the repr is coloured by on-disk type via LS_COLORS.

See Also

pyrfs.path : Functional construction with an ext= option. as_pathlib : Convert when you want pathlib semantics.

Examples:

>>> FsPath("src//a.txt/")  # tidied on construction
FsPath('src/a.txt')
>>> (FsPath("foo") / "bar" / "a.txt").with_ext("md")
FsPath('foo/bar/a.md')
>>> FsPath("a/b").startswith("a")  # still a str
True

__truediv__

__truediv__(other: str | PathLike[str]) -> FsPath

Join with other: FsPath('a') / 'b' -> FsPath('a/b').

Concatenation + tidy: an absolute right-hand side does not reset the path (unlike pathlib/os.path.join).

__rtruediv__

__rtruediv__(other: str | PathLike[str]) -> FsPath

Support 'a' / FsPath('b') joining from a plain string.

ext

ext() -> str

Extension without the dot ('' if none) — pyrfs.path_ext.

with_ext

with_ext(ext: str) -> FsPath

Replace (or add) the extension; '' removes it — pyrfs.path_ext_set.

Examples:

>>> (FsPath("data") / "raw.csv").with_ext("parquet")
FsPath('data/raw.parquet')

dir

dir() -> FsPath

Directory part of the path ('.' if none) — pyrfs.path_dir.

name

name() -> FsPath

File name — the last path component — pyrfs.path_file.

parts

parts() -> list[str]

Path components (a leading root stays '/') — pyrfs.path_split.

Named parts (as in pathlib) so str.split keeps its normal string behavior.

Examples:

>>> FsPath("/usr/bin").parts()
['/', 'usr', 'bin']

rel_to

rel_to(start: str | PathLike[str]) -> FsPath

This path expressed relative to startpyrfs.path_rel.

has_parent

has_parent(parent: str | PathLike[str]) -> bool

Whether this path sits at or below parentpyrfs.path_has_parent.

expand

expand() -> FsPath

Expand a leading ~ to the home directory — pyrfs.path_expand.

norm

norm() -> FsPath

Normalize . and .. lexically — pyrfs.path_norm.

abs

abs() -> FsPath

Absolute form (links unresolved) — pyrfs.path_abs.

real

real() -> FsPath

Canonical form, symlinks resolved — pyrfs.path_real.

copy_to

copy_to(new_path: str | PathLike[str], *, overwrite: bool = False) -> FsPath

Copy this file to new_pathpyrfs.file_copy.

Copying into an existing directory targets new_path/basename; an existing destination raises FileExistsError unless overwrite=True. Returns the new copy's path (chains).

move_to

move_to(new_path: str | PathLike[str], *, overwrite: bool = False) -> FsPath

Move (rename) this file or directory — pyrfs.file_move.

Same destination resolution and overwrite guard as copy_to.

create

create(*, mode: int | str = 420) -> FsPath

Create this file (existing files untouched) — pyrfs.file_create.

touch

touch() -> FsPath

Update timestamps, creating the file if needed — pyrfs.file_touch.

delete

delete() -> None

Delete this file or symlink — pyrfs.file_delete.

Returns None: a deleted path has nothing to chain onto. For directories use rmdir.

exists

exists() -> bool

Whether this path exists (broken symlinks count) — pyrfs.file_exists.

access

access(mode: str = 'exists') -> bool

Test "exists"/"read"/"write"/"execute"pyrfs.file_access.

size

size() -> Bytes

File size as a pyrfs.Bytes value — pyrfs.file_size.

Examples:

>>> FsPath("notes.txt").create().size() == 0
True

chmod

chmod(mode: int | str) -> FsPath

Change permissions — pyrfs.file_chmod.

Symbolic modes ("u+x") apply to the current mode; octal and display forms are absolute. Returns this path (chains).

info

info() -> dict[str, object]

Stat this path into one row of typed values — pyrfs.file_info.

Returns a single dict (use the functional pyrfs.file_info / pyrfs.dir_info for tables).

mkdir

mkdir(*, mode: int | str = 493, recurse: bool = True) -> FsPath

Create this directory (parents too when recurse) — pyrfs.dir_create.

Examples:

>>> FsPath("proj").mkdir().touch_file("README.md").ls()
[FsPath('proj/README.md')]

rmdir

rmdir() -> None

Delete this directory and everything below it — pyrfs.dir_delete.

Recursive (rm -rf semantics), despite the os.rmdir-like name. Returns None: nothing left to chain onto.

touch_file

touch_file(name: str | PathLike[str]) -> FsPath

Create a child file and return this directory (keeps chaining).

Returning the directory (not the new file) lets several touch_file calls chain; use (p / name).touch() when you want the file's path back.

ls

ls(*, all: bool = False, recurse: bool | int = False, type: str | Iterable[str] = 'any', glob: str | None = None, regexp: str | None = None, invert: bool = False, fail: bool = True) -> list[FsPath]

List entries of this directory — pyrfs.dir_ls (same filters).

walk

walk(*, all: bool = False, recurse: bool | int = True, type: str | Iterable[str] = 'any', glob: str | None = None, regexp: str | None = None, invert: bool = False, fail: bool = True) -> Iterator[FsPath]

Lazily yield entries below this directory — pyrfs.dir_walk.

Unlike the functional default, recurse=True here: walking a tree is the common fluent use.

tree

tree(*, recurse: bool | int = True, all: bool = False) -> None

Print a box-drawing tree of this directory — pyrfs.dir_tree.

is_file

is_file() -> bool

Whether this is a regular file (lstat; symlinks answer False) — pyrfs.is_file.

is_dir

is_dir() -> bool

Whether this is a directory (lstat; symlinks answer False) — pyrfs.is_dir.

is_link() -> bool

Whether this is a symlink — pyrfs.is_link.

as_pathlib

as_pathlib() -> pathlib.Path

This path as a pathlib.Path, when you want pathlib semantics.

Examples:

>>> FsPath("a/b").as_pathlib()
PosixPath('a/b')