Python pathlib Examples
Short, runnable programs that show python pathlib in action. Read the explanation, press Run, then change the code and try your own ideas. New to the topic? Start with the Python pathlib lesson.
1Organise files by extension
Each file is moved into a sub-folder named after its suffix. suffix.lstrip(".") turns .txt into txt, mkdir(exist_ok=True) creates the folder only once, and rename() moves the file. The result is printed with rglob and relative_to.
from pathlib import Path
import shutil
inbox = Path("inbox")
inbox.mkdir(exist_ok=True)
for name in ["notes.txt", "photo.png", "budget.csv", "todo.txt", "logo.png"]:
(inbox / name).write_text("demo")
for file in sorted(inbox.iterdir()):
if file.is_file():
target = inbox / file.suffix.lstrip(".")
target.mkdir(exist_ok=True)
file.rename(target / file.name)
for file in sorted(inbox.rglob("*")):
if file.is_file():
print(file.relative_to(inbox).as_posix())
shutil.rmtree(inbox)Expected outputcsv/budget.csv
png/logo.png
png/photo.png
txt/notes.txt
txt/todo.txt
2Count the lines in every .txt file
glob("*.txt") matches only the text files, so ideas.md is ignored. read_text().splitlines() gives the lines of each file, and sorted() makes the order predictable.
from pathlib import Path
import shutil
notes = Path("notes")
notes.mkdir(exist_ok=True)
(notes / "monday.txt").write_text("call Sam\nbuy milk\nfix bike\n")
(notes / "tuesday.txt").write_text("gym\n")
(notes / "ideas.md").write_text("not a txt file\n")
total = 0
for file in sorted(notes.glob("*.txt")):
lines = len(file.read_text().splitlines())
total += lines
print(f"{file.name}: {lines} line(s)")
print("Total:", total)
shutil.rmtree(notes)Expected outputmonday.txt: 3 line(s)
tuesday.txt: 1 line(s)
Total: 4
3Build a report path and its relatives
One function builds the path. with_name() and with_suffix() calculate sibling paths without touching the disk, which is why only the original file exists at the end.
from pathlib import Path
import shutil
def report_path(year, month):
return Path("exports") / str(year) / f"sales_{month:02d}.csv"
path = report_path(2025, 3)
print(path)
print(path.parent.name, path.stem)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("month,total\n3,120\n")
backup = path.with_name(path.stem + "_backup" + path.suffix)
print(backup)
print(path.with_suffix(".txt"))
print(path.exists(), backup.exists())
shutil.rmtree("exports")Expected outputexports/2025/sales_03.csv
2025 sales_03
exports/2025/sales_03_backup.csv
exports/2025/sales_03.txt
True False
4Search every sub-folder with rglob
rglob("*.py") finds Python files at every depth. relative_to() removes the project folder from the front, and counting the parts tells you how deep each file sits.
from pathlib import Path
import shutil
project = Path("project")
for name in ["main.py", "utils/helpers.py", "utils/tests/test_helpers.py", "README.md"]:
file = project / name
file.parent.mkdir(parents=True, exist_ok=True)
file.write_text("# demo\n")
for file in sorted(project.rglob("*.py")):
relative = file.relative_to(project)
print(relative.as_posix(), "- depth", len(relative.parts) - 1)
shutil.rmtree(project)Expected outputmain.py - depth 0
utils/helpers.py - depth 1
utils/tests/test_helpers.py - depth 2
5Check a path before you use it
exists() guards against missing files, and stat().st_size separates empty files from real ones. is_dir() shows that a file and the folder that contains it are different things.
from pathlib import Path
import shutil
folder = Path("uploads")
folder.mkdir(exist_ok=True)
(folder / "photo.png").write_text("x" * 2500)
(folder / "empty.txt").write_text("")
for name in ["photo.png", "empty.txt", "missing.pdf"]:
path = folder / name
if not path.exists():
print(name, "-> not found")
elif path.stat().st_size == 0:
print(name, "-> empty file")
else:
print(name, "->", path.stat().st_size, "bytes")
print(folder.is_dir(), (folder / "photo.png").is_dir())
shutil.rmtree(folder)Expected outputphoto.png -> 2500 bytes
empty.txt -> empty file
missing.pdf -> not found
True False
6Delete safely with unlink and rmdir
rmdir() refuses to remove a folder that still has files in it. unlink() removes the file, and missing_ok=True makes a second delete harmless. Only then can the empty folder go.
from pathlib import Path
folder = Path("scratch")
folder.mkdir(exist_ok=True)
temp = folder / "temp.txt"
temp.write_text("temporary")
try:
folder.rmdir()
except OSError:
print("rmdir refused: the folder is not empty")
temp.unlink()
temp.unlink(missing_ok=True)
folder.rmdir()
print("folder exists:", folder.exists())Expected outputrmdir refused: the folder is not empty
folder exists: False
Practise next
Python pathlib exercises → Back to the lesson
Python File Handling examplesPython with Statement examplesWorking with JSON in Python examplesPython CSV Files examples