Pathlib Tricks Beyond Basic File Ops
Discover lesser-known Path methods like with_name(), resolve(), rglob(), and PurePath to write tighter, platform-safe file handling code in Python.
You're probably already using Python's pathlib to read files and list directories. That's fine—but you're missing out. The Path object hides a bunch of tricks that will save you hours of debugging and make your file handling code much tighter.
The with_name() and with_suffix() Shortcuts
Need to change a file's name or extension without rebuilding the whole path? Stop slicing strings.
from pathlib import Path
config = Path("/home/pythonskillset/projects/data/v1/config.yaml")
# Change the version folder
moved = config.with_name("v2").with_suffix(".json")
print(moved) # /home/pythonskillset/projects/data/v2/config.json
No .parent chaining. No .split(). Just clean, readable transformations.
Walk Files With rglob() and Filter by Type
rglob() is the modern replacement for os.walk. But here's the part people skip—you can filter during the walk:
from pathlib import Path
logs = Path("/var/log/pythonskillset")
# Only .log files modified today
recent = [f for f in logs.rglob("*.log")
if f.stat().st_mtime > (time.time() - 86400)]
Add file size checks, date ranges, or custom extensions in one pass. No separate filtering loops needed.
The absolute() vs resolve() Trap
These look identical—until they don't:
absolute()just prepends the current working directory. It does nothing if the path is already relative.resolve()evaluates symlinks and normalizes..components.
link = Path("/home/pythonskillset/shortcut/data")
print(link.absolute()) # /home/pythonskillset/shortcut/data
print(link.resolve()) # /mnt/storage/pythonskillset/actual/data (if shortcut is symlink)
Use resolve() when you need the real location. Use absolute() when you just need a full path for display.
PurePath for Platform-Safe Operations
Working with paths across Windows and Linux? PurePath does string operations without touching the filesystem:
from pathlib import PurePosixPath, PureWindowsPath
unix = PurePosixPath("/home/pythonskillset/scripts/backup.sh")
win = PureWindowsPath("C:\\Users\\pythonskillset\\scripts\\backup.sh")
# Same operations, different separators
print(unix.stem) # backup
print(win.stem) # backup
No disk access, no permission errors. Just safe path manipulation.
The Hidden stat() Methods
You probably know Path.stat(). But did you know you can get specific details directly?
import os
from pathlib import Path
f = Path("/etc/pythonskillset.conf")
# Compare file times without extracting timestamps
print(f.stat().st_mtime) # raw timestamp
print(f.stat().st_size) # bytes
# Check if two paths point to the same file
a = Path("/tmp/conf")
b = Path("/tmp/conf_backup")
if a.stat().st_ino == b.stat().st_ino:
print("Same file, different names")
For large file listings, batch-stat with os.stat instead of calling .stat() on every path in a loop. But for one-off checks, this is perfect.
touch() for Atomic File Creation
Path.touch() doesn't just update timestamps—it creates files atomically:
lock = Path("/tmp/pythonskillset_deploy.lock")
try:
lock.touch(exist_ok=False) # raises FileExistsError if present
# ... do deployment ...
finally:
lock.unlink()
Use this as a lightweight mutex for scripts that shouldn't run twice simultaneously.
Real-World Example: Log Rotation in 5 Lines
from pathlib import Path
from datetime import datetime, timedelta
logs = Path("/var/log/pythonskillset")
cutoff = datetime.now() - timedelta(days=30)
for old in logs.rglob("*.log.gz"):
if datetime.fromtimestamp(old.stat().st_mtime) < cutoff:
old.unlink()
No os.listdir, no os.path.getmtime, no worry about trailing slashes. pathlib handles all that.
Last Tip: Don't Use os.path Anymore
Every function in os.path has a pathlib equivalent, and the pathlib version is more readable and less error-prone. If you're still writing os.path.join(os.path.dirname(__file__), "templates"), stop. Write Path(__file__).parent / "templates". Your future self will thank you.
The full power of pathlib shines when you stop treating it as a fancy string class and start using its object-oriented features. Once you internalize with_name, resolve, and the pure path family, you'll wonder how you ever managed without them.
Comments
Questions, corrections, and tips stay visible for everyone reading this page.
Join the discussion
No comments yet
Be the first to leave a note — it helps the next reader.