Python pathlib · Examples
Core Python

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.

Organise files by extension
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.

Count the lines in every .txt file
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.

Build a report path and its relatives
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.

Search every sub-folder with rglob
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.

Check a path before you use it
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.

Delete safely with unlink and rmdir
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