pathlib cheatsheet — use this instead of os.path in modern Python.
Construct
from pathlib import Path
p = Path("/var/log/app.log")
p = Path("data") / "users.csv" # joining
p = Path.home() / ".config" / "app"
p = Path.cwd() # current dir
Common paths
Path.home() # ~
Path.cwd() # current working dir
Path(__file__).parent # dir of current file
Path(__file__).resolve() # absolute path
Properties
p = Path("/var/log/app.log")
p.name # "app.log"
p.stem # "app"
p.suffix # ".log"
p.suffixes # [".log"]
p.parent # Path("/var/log")
p.parts # ("/", "var", "log", "app.log")
p.anchor # "/"
Checks
p.exists()
p.is_file()
p.is_dir()
p.is_symlink()
p.is_absolute()
Read / write
# Text
p.read_text(encoding="utf-8")
p.write_text("hello", encoding="utf-8")
# Bytes
data = p.read_bytes()
p.write_bytes(b"...")
# Lines
for line in p.read_text().splitlines():
...
Open as context manager
with p.open("r") as f:
content = f.read()
with p.open("wb") as f:
f.write(b"data")
Create / delete
p.mkdir()
p.mkdir(parents=True, exist_ok=True) # like mkdir -p
p.unlink() # delete file
p.unlink(missing_ok=True)
p.rmdir() # remove empty dir
import shutil
shutil.rmtree(p) # remove dir + contents
Move / rename
p.rename("new_name.txt")
p.replace("new_name.txt") # overwrites destination
# Within same FS
new = p.parent / "new_name.txt"
p.rename(new)
Copy
import shutil
shutil.copy(src, dst)
shutil.copy2(src, dst) # preserves metadata
shutil.copytree(src_dir, dst_dir)
Traverse
# Direct children
for child in p.iterdir():
print(child)
# Glob
for f in p.glob("*.txt"):
...
# Recursive
for f in p.rglob("*.py"):
...
# Glob with patterns
list(p.glob("**/*.json")) # all .json recursive
list(p.glob("data/[0-9]*.csv")) # data/0.csv, data/1.csv, ...
Stat / metadata
s = p.stat()
s.st_size # bytes
s.st_mtime # modified time (epoch)
from datetime import datetime
datetime.fromtimestamp(s.st_mtime)
Match patterns
p.match("*.txt") # bool
p.match("**/*.py")
Resolve symlinks / absolute
p.resolve() # absolute, symlinks resolved
p.absolute() # absolute, symlinks not resolved
p.expanduser() # ~ → home dir
Common patterns
# Read JSON
import json
data = json.loads(p.read_text())
p.write_text(json.dumps(data))
# Read CSV
import csv
with p.open() as f:
reader = csv.DictReader(f)
for row in reader: ...
# Touch (create empty file or update mtime)
p.touch()
p.touch(exist_ok=False) # error if exists
# Walk dir tree (like os.walk)
for root, dirs, files in os.walk(p):
...
# Or with pathlib
def walk(p):
for child in p.iterdir():
yield child
if child.is_dir():
yield from walk(child)
Cross-platform
Path("/var/log/app.log") # works on Linux/Mac
Path("C:/Users/me/file.txt") # works on Windows
Path("a") / "b" / "c" # forward slashes auto
# Force POSIX or Windows
from pathlib import PurePosixPath, PureWindowsPath
Tmp paths
import tempfile
with tempfile.TemporaryDirectory() as tmp:
p = Path(tmp) / "x.txt"
p.write_text("hi")
# dir cleaned up
with tempfile.NamedTemporaryFile(delete=False) as f:
f.write(b"data")
name = f.name
Common mistakes
- Mixing
os.pathandpathlib— pick one. str(p) + "/sub"— usep / "sub".p.unlink()withoutmissing_ok=True— error if missing.glob("*.py")when you want recursive — userglob.
Read this next
If you want my pathlib utilities library, it’s at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .