Files and Folders with pathlib

First lesson of the Automate with Python (Files, Excel, APIs) course, free to read: about 15 minutes, 3 exercises and 3 quiz questions. This is the catalogue's base lesson; in the student space, it is rewritten for your profile.

Objectives

  • Build portable paths with pathlib
  • Read and write text files, specifying the encoding
  • Browse, create, rename and organize the files in a folder

pathlibReading and writing filesOrganizing folders

Files and Folders with pathlib

Automating starts with handing repetitive file handling over to Python: sorting exports, renaming reports, merging the month’s files. The standard pathlib module makes these operations simple and portable.

Portable paths

from pathlib import Path

dossier = Path("rapports") / "2026"          # the / operator joins the pieces
fichier = dossier / "ventes_novembre.csv"
print(fichier)            # rapports/2026/ventes_novembre.csv (or with \ on Windows)

print(fichier.name)       # ventes_novembre.csv
print(fichier.stem)       # ventes_novembre
print(fichier.suffix)     # .csv
print(fichier.parent)     # rapports/2026
print(fichier.with_suffix(".xlsx").name)  # ventes_novembre.xlsx

Path.cwd()                # current working directory
Path.home()               # the user's home directory

No more concatenating strings with "/" or "\\": pathlib picks the right separator for the system.

Reading and writing text

notes = Path("notes.txt")
notes.write_text("Première ligne\nDeuxième ligne\n", encoding="utf-8")
contenu = notes.read_text(encoding="utf-8")
print(contenu.splitlines())   # ['Première ligne', 'Deuxième ligne']

# To read or write as you go, line by line:
with notes.open("a", encoding="utf-8") as f:   # "a": append to the end of the file
    f.write("Troisième ligne\n")

with notes.open(encoding="utf-8") as f:        # read by default ("r")
    for ligne in f:
        print(ligne.rstrip("\n"))

The with block closes the file automatically, even on error. Always specify encoding="utf-8": before Python 3.15, the default encoding depends on the system (often different on Windows), a classic source of unreadable accented characters. Python 3.15 uses UTF-8 by default everywhere, but specifying it remains the rule: the intent is explicit and the code behaves the same way with earlier versions. The modes: "r" read, "w" write (overwrites!), "a" append, "x" create (error if the file exists).

Browsing a folder

exports = Path("exports")
for chemin in sorted(exports.glob("*.csv")):      # .csv files in the folder
    print(chemin.name, chemin.stat().st_size, "bytes")

tous = list(exports.rglob("*.csv"))               # rglob: also in subfolders
dossiers = [p for p in exports.iterdir() if p.is_dir()]

Creating, moving, organizing

archive = Path("archive") / "2026-11"
archive.mkdir(parents=True, exist_ok=True)   # also creates parents, no error if it exists

for chemin in Path("exports").glob("*.csv"):
    destination = archive / chemin.name
    chemin.replace(destination)               # moves (and overwrites if the target exists)

chemin.unlink() deletes a file; for a non-empty folder, the shutil module offers shutil.rmtree and shutil.copy2 to copy. Be careful: a delete or move loop acts on hundreds of files in a second. Always test your script on a temporary folder:

import tempfile
with tempfile.TemporaryDirectory() as tmp:
    base = Path(tmp)
    (base / "essai.csv").write_text("a,b\n1,2\n", encoding="utf-8")
    print([p.name for p in base.iterdir()])
# the temporary folder and its contents are deleted on leaving the block

This is exactly what the exercises in this lesson do.

Key takeaways

  • Path + / for portable paths; name, stem, suffix, parent.
  • read_text / write_text or with open(...), always with encoding="utf-8".
  • glob, mkdir(parents=True, exist_ok=True), replace; test on a temporary folder.

Exercises

Solutions and tests stay on the server. In the student space, your code is run and checked, and the tutor gives hints before the solution.

  1. CodeDifficulty 1Python in the browser2 hints

    Decompose and build paths

    From source, compute:

    • nom: the file name with extension;
    • base: the name without extension;
    • extension: the extension (with the dot);
    • sortie: a Path to the same name with .xlsx, placed in the rapports subfolder of source’s parent folder.
    from pathlib import Path
    
    source = Path("donnees") / "2026" / "ventes_novembre.csv"
    
    nom = ...
    base = ...
    extension = ...
    sortie = ...
  2. CodeDifficulty 2Python in the browser2 hints

    Merge the text files in a folder

    Write fusionner(dossier, motif="*.txt") that reads, in alphabetical order of names, all the files in the folder matching the pattern, and returns the list of all their non-empty lines (without the newline). Also write ecrire_lignes(chemin, lignes) that writes the lines to a UTF-8 file, one per line, creating parent folders if needed.

    The test code creates a temporary folder; do not touch the disk outside it.

    from pathlib import Path
    
    def fusionner(dossier, motif="*.txt"):
        ...
    
    def ecrire_lignes(chemin, lignes):
        ...
  3. Multiple choiceDifficulty 11 hint

    Opening mode

    You want to add a line to the end of an existing log without erasing its contents. Which mode should you use?

    • "w"
    • "a"
    • "r"
    • "x"

End-of-lesson quiz

  1. What is Path("a/rapport.final.csv").suffix?

    • ".final.csv"
    • ".csv"
    • "csv"
  2. Why use with open(...) as f:?

    • It is faster
    • The file is closed automatically, even on error
    • It is required for reading
  3. What does Path("out/2026").mkdir(parents=True, exist_ok=True) do if the folder already exists?

    • Raises an error
    • Does nothing, with no error
    • Empties the folder

The rest of the course

  1. Reading and Writing CSV and JSON20 min
  2. Automating Excel with pandas and openpyxl20 min
  3. Querying a Web API20 min
  4. An End-to-End Automated Script20 min

Automate with Python (Files, Excel, APIs) · Intermediate · 3 h 5 min