List all files in a directory with Python is a common task that developers encounter when building scripts for file management, data processing, or automation. Knowing how to retrieve file names efficiently lets you iterate over datasets, perform batch operations, or generate reports without manual intervention. This guide walks you through the most reliable ways to list files using Python’s standard library, explains when each method shines, and provides practical code snippets you can adapt to your projects.
Why You Might Need to List Files
Before diving into code, it helps to clarify the typical scenarios where a file‑listing routine is useful:
- Batch processing – applying the same transformation to every image, CSV, or log file in a folder.
- Backup or synchronization – identifying new or changed files to copy to another location.
- Data ingestion – loading all files that match a pattern (e.g.,
*.json) into a pipeline. - Cleanup routines – finding temporary or stale files older than a certain date for deletion.
- Reporting – generating an inventory of files, sizes, and modification times for audits.
Understanding the context helps you choose the right tool: sometimes you need just the names, other times you require full paths, metadata, or recursive traversal.
Core Techniques in Python’s Standard Library
Python offers several built‑in modules for directory traversal. Each has its own strengths, and picking the appropriate one can improve readability and performance.
1. Using os.listdir()
The simplest approach is os.listdir(path), which returns a list of entry names (strings) inside the given directory Easy to understand, harder to ignore. And it works..
import os
def list_files_basic(directory):
"""Return a list of all entries (files and subdirectories) in *directory*."""
return os.listdir(directory)
# Example usage
entries = list_files_basic('/tmp/my_folder')
print(entries)
Pros
- Extremely short and easy to understand.
- Works on all platforms supported by Python.
Cons
- Returns both files and directories; you must filter if you need only files.
- Does not provide file metadata (size, timestamps) without extra calls.
- Not recursive; you need to handle subfolders manually.
2. Filtering with os.scandir()
For better performance—especially when you need attributes—os.scandir() yields DirEntry objects that expose useful properties like is_file(), stat(), and path.
import os
def list_files_scandir(directory):
"""Yield full paths of files only, using scandir for efficiency.In real terms, """
with os. scandir(directory) as it:
for entry in it:
if entry.is_file():
yield entry.
# Example usage
for file_path in list_files_scandir('/tmp/my_folder'):
print(file_path)
Pros
- Faster than
listdir()+stat()because the OS returns basic info in one system call. - Allows easy filtering (files vs. directories) without extra
os.pathcalls. - Supports the context‑manager pattern, ensuring the iterator is closed properly.
Cons
- Slightly more verbose than
listdir(). - Still non‑recursive; you must implement recursion yourself if needed.
3. Leveraging pathlib.Path
Introduced in Python 3.That said, the Path. That's why 4, pathlib provides an object‑oriented interface that many developers find more intuitive. iterdir() method works similarly to scandir() but returns Path objects It's one of those things that adds up..
from pathlib import Path
def list_files_pathlib(directory):
"""Return a list of Path objects for files in *directory*."""
p = Path(directory)
return [item for item in p.iterdir() if item.
# Example usage
for file_path in list_files_pathlib('/tmp/my_folder'):
print(file_path)
Pros
- Readable, chainable API (
Path / 'subdir' / 'file.txt'). - Handles path separators automatically across OSes.
- Easy to access attributes like
.stat(),.name,.suffix.
Cons
- Slight overhead compared to raw
oscalls, though negligible for most scripts. - Requires Python 3.4+.
4. Using glob for Pattern Matching
Every time you need to filter by extension or naming pattern, glob.It supports Unix‑style wildcards (*, ?glob()(orPath.Day to day, rglob()) is handy. , [seq]).
import glob
import os
def list_files_glob(directory, pattern='*'):
"""Return paths matching *pattern* inside *directory* (non‑recursive)."""
search_path = os.path.join(directory, pattern)
return glob.
# Example: list all .txt files
txt_files = list_files_glob('/tmp/my_folder', '*.txt')
print(txt_files)
Pros
- Directly filters by name pattern, reducing post‑processing.
- Works with both
osandpathlib(Path.glob()).
Cons
- Still non‑recursive unless you use
**(Python 3.5+). - Returns a list, which may consume memory for huge directories.
5. Recursive Listing with os.walk() or Path.rglob()
For walking an entire directory tree, os.Which means walk() is the classic solution. It yields a tuple (root, dirs, files) for each directory it visits And it works..
import os
def list_files_walk(root_dir):
"""Recursively yield full paths of all files under *root_dir*.walk(root_dir):
for f in files:
yield os."""
for root, _, files in os.path.
# Example usage
for file_path in list_files_walk('/tmp/my_folder'):
print(file_path)
Pros
- Fully recursive, depth‑first traversal.
- Allows you to modify the
dirslist in‑place to prune unwanted subdirectories.
Cons
- Slightly more verbose if you only need a flat list.
- The generator yields tuples; you must unpack or ignore unwanted elements.
With pathlib, the same task becomes a one‑liner using rglob():
from pathlib import Path
def list_files_pathlib_recursive(directory):
"""Recursively yield Path objects for all files."""
return Path(directory).rglob('*')
# Example: only .csv files
csv_files = [p for p in list_files_pathlib_recursive('/tmp/my_folder') if p.is_file() and p.suffix == '.csv']
Pros
- Concise and expressive.
- Works well with additional filters (`if p.is_file