Creating, moving and deleting

pathlib · Practical · 9 min

Output folders, temp files and archiving steps are part of nearly every script.

Path wraps the common file operations:

  • p.mkdir(parents=True, exist_ok=True) creates the directory and missing parents, and doesn't complain if it exists.
  • p.touch() creates an empty file or updates its modification time; touch(exist_ok=False) fails if it exists.
  • p.rename(target) moves or renames and returns the new Path. On Windows it fails if target exists.
  • p.replace(target) does the same but overwrites target on every platform (atomic on POSIX).
  • p.unlink(missing_ok=True) deletes a file, ignoring it if absent.
  • p.rmdir() deletes an empty directory.

Relative targets in rename and replace are interpreted relative to the current working directory, not to p's folder. Write p.rename(p.with_name("new.txt")) or p.parent / "new.txt" to stay in the same directory.

Pathlib in 3.13 has no recursive delete or copy; use shutil.rmtree(p), shutil.copy2(src, dst) and shutil.move(src, dst), which all accept Path objects. (Python 3.14 adds Path.copy and Path.move.)

All these methods raise the usual OSError subclasses: FileExistsError, FileNotFoundError, IsADirectoryError, PermissionError.

Example

import shutil
from pathlib import Path

out = Path("out/2025/03")
out.mkdir(parents=True, exist_ok=True)
draft = out / "draft.txt"
draft.write_text("v1", encoding="utf-8")

final = draft.rename(draft.with_name("final.txt"))   # same folder
print(final)                          # out/2025/03/final.txt
print(draft.exists())                 # False

(out / "tmp.lock").touch()
(out / "tmp.lock").unlink()
(out / "tmp.lock").unlink(missing_ok=True)   # no error when absent

try:
    Path("out").rmdir()
except OSError as e:
    print(type(e).__name__)           # OSError
shutil.rmtree("out")
print(Path("out").exists())           # False

Remember

  • mkdir(parents=True, exist_ok=True) ensures a folder exists
  • rename targets are relative to the cwd; build them from p.parent or with_name
  • Use shutil for recursive delete, copy and cross-device moves

Watch out for

  • Writing p.rename('new.txt') and finding the file moved into the current working directory.

Check yourself

  1. p = Path('data/raw/a.csv'). Where does p.rename('b.csv') put the file?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/pathlib.html#pathlib.Path.rename

Creating, moving and deleting · pathlib · Topolearn