HOWTO · Python
How to List All Files in Directory and Subdirectories in Python
This tutorial demonstrates how to list all files in a directory and subdirectories in Python.
On this page
To collect paths for every file beneath a starting directory, use Python’s os.walk(). It visits the directory tree and yields each current directory, its child-directory names, and its file names. Join the current directory with each file name to build a path. The examples here list files rather than directory entries.
Run this example:
from pathlib import Path
import os
import tempfile
with tempfile.TemporaryDirectory() as temporary_directory:
root = Path(temporary_directory) / "project"
(root / "reports").mkdir(parents=True)
for relative_path in ("notes", "data.csv", "reports/summary.txt", "reports/2025.csv"):
(root / relative_path).write_text("sample", encoding="utf-8")
for current, directories, filenames in os.walk(root):
directories.sort()
for filename in sorted(filenames):
print(Path(current, filename).relative_to(root))
data.csv
notes
reports/2025.csv
reports/summary.txt
This temporary example creates its own directory tree, including a file without an extension, and prints paths relative to the starting directory. Use Path(current, filename) or os.path.join(current, filename) to construct full paths instead. A relative path is convenient when storing results; an absolute path is useful when passing files to other code. Path separators are chosen for the current operating system.
Use os.walk() to list files recursively
The loop above uses os.walk() as the default for straightforward recursive listing. On every iteration, its first value is the current directory path, its second is a mutable list of child directory names, and its third is the file names in that current directory. Iterate over the third value to avoid including directories. Sort the child names when a stable traversal order matters. By default, traversal errors are ignored; supply onerror if your application needs to report them.
Use os.listdir() for a custom recursive traversal
os.listdir(path) returns the names of entries in one directory; it does not visit child directories. For custom traversal, maintain a stack of paths to inspect. For each path, iterate over os.listdir(path), join each name to its parent with os.path.join(), append files to the result, and add directories to the stack. Check entries with os.path.isfile() and os.path.isdir(). This approach gives control over traversal order and filtering, but your code must handle the recursion and filesystem errors.
Use os.scandir() to inspect directory entries
os.scandir(path) yields DirEntry objects for one directory. Their is_file() and is_dir() methods make it convenient to decide what to collect and whether to visit a child directory. Apply the same stack-based traversal described above, opening each directory with with os.scandir(path) as entries: so its iterator is closed reliably. This is useful when entry type or metadata affects your decision.
Use glob.glob() to match files by pattern
For pattern-based selection, glob.glob(os.path.join(root, "**", "*"), recursive=True) matches names at any depth, including names without extensions. The ** component spans directories when recursive=True is enabled. Glob results can include directories, so filter them with os.path.isfile(path) when the result must contain files only. Use a narrower pattern such as "**/*.csv" to select a file type; "*.*" excludes names that have no dot.
Use pathlib.Path to list files recursively
pathlib.Path(root).rglob("*") yields paths beneath the root recursively. Filter the results with path.is_file() to omit directories. The returned objects are Path instances, so methods such as relative_to(root) and name are available without manually joining strings. Use str(path) when an API requires a string path.
Choose a method based on the task
Choose os.walk() for a clear default that separates file names from child-directory names. Choose os.scandir() when inspecting entry types or metadata during traversal. Use glob.glob() when matching a pattern, and pathlib.Path.rglob() when working with path objects. Choose os.listdir() when you need a custom traversal policy and are prepared to implement it. These approaches return paths or names, not file contents; open a path separately to read or process a file. For a missing or unreadable starting directory, handle filesystem errors according to the API and behavior your application requires.