Checking and listing paths

pathlib · Essentials · 7 min

Scripts constantly need to know whether an input exists and what files a folder holds.

These methods ask the file system:

  • p.exists() true if anything is there (following symlinks)
  • p.is_file(), p.is_dir(), p.is_symlink()
  • p.stat().st_size size in bytes, p.stat().st_mtime modification time

They return False rather than raising when the path is missing or inaccessible. Since 3.12, exists, is_file and is_dir take follow_symlinks=False to inspect links themselves.

p.iterdir() yields a Path for each entry in the directory, already joined with p, in arbitrary order. Unlike os.listdir, you get usable paths, not bare names:

csvs = sorted(f for f in folder.iterdir() if f.suffix == ".csv")

iterdir raises NotADirectoryError if p is a file and FileNotFoundError if it's missing.

Checking before acting is fine for user-facing messages ("input file not found"), but for correctness it can race: the file can vanish between exists() and read_text(). When it matters, just attempt the operation and catch FileNotFoundError.

For recursive listings, use glob/rglob or Path.walk() instead of nesting iterdir calls by hand.

Example

from pathlib import Path

folder = Path("inbox")
folder.mkdir()
for name in ["b.csv", "a.csv", "readme.md"]:
    (folder / name).write_text("x", encoding="utf-8")
(folder / "archive").mkdir()

print(folder.exists(), folder.is_dir())          # True True
print(sorted(p.name for p in folder.iterdir()))  # ['a.csv', 'archive', 'b.csv', 'readme.md']
csvs = sorted(p for p in folder.iterdir() if p.is_file() and p.suffix == ".csv")
print(csvs)          # [PosixPath('inbox/a.csv'), PosixPath('inbox/b.csv')]
print((folder / "nope.txt").exists())            # False
print((folder / "a.csv").stat().st_size)         # 1

Remember

  • exists, is_file and is_dir return False instead of raising
  • iterdir() yields full Path objects in arbitrary order
  • Prefer try/except over check-then-act when correctness matters

Watch out for

  • Sorting by assuming iterdir returns alphabetical order; it doesn't.

Check yourself

  1. folder = Path('docs'). What does next(folder.iterdir()) return if docs contains intro.md?

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.iterdir