Python
File Management
Directory
Programming
Tutorial

How to count the number of files in a directory using Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Counting files sounds trivial, but the exact answer depends on the scope of the search. You need to decide whether the count includes only one directory or every nested folder, whether symlinks count as files, and whether permission failures should stop the scan.

Count Files In One Directory

For a simple non-recursive count, pathlib is a good default. It makes the code readable and gives you Path objects instead of raw strings.

python
1from pathlib import Path
2
3folder = Path("/tmp/example")
4count = sum(1 for entry in folder.iterdir() if entry.is_file())
5
6print(count)

This counts regular files directly inside folder and ignores subdirectories. The generator expression is efficient because it streams the count instead of collecting every path in memory.

If the task is "count only Python files" or "count only CSV exports," add the filter where you count:

python
1from pathlib import Path
2
3folder = Path("/tmp/example")
4py_files = sum(
5    1
6    for entry in folder.iterdir()
7    if entry.is_file() and entry.suffix == ".py"
8)
9
10print(py_files)

That is usually enough for scripts that inspect one known folder.

Use os.scandir When Performance Matters

When a directory contains many entries, os.scandir is often faster than older patterns because each DirEntry can answer is_file() efficiently.

python
1import os
2
3path = "/tmp/example"
4count = 0
5
6with os.scandir(path) as entries:
7    for entry in entries:
8        if entry.is_file():
9            count += 1
10
11print(count)

This is a strong choice for high-volume folders or command-line tools where speed matters. It also makes it easy to skip hidden files or match a naming pattern.

python
1import os
2
3path = "/tmp/example"
4count = 0
5
6with os.scandir(path) as entries:
7    for entry in entries:
8        if entry.name.startswith("."):
9            continue
10        if entry.is_file() and entry.name.endswith(".csv"):
11            count += 1
12
13print(count)

That code counts only visible CSV files in the top-level directory.

Count Files Recursively

If the real requirement is "count everything below this root," switch to a recursive API. Path.rglob keeps the code compact:

python
1from pathlib import Path
2
3root = Path("/tmp/example")
4count = sum(1 for entry in root.rglob("*") if entry.is_file())
5
6print(count)

os.walk is another standard tool and is especially useful when you also need the directory names while traversing:

python
1import os
2
3root = "/tmp/example"
4count = 0
5
6for current_dir, dirnames, filenames in os.walk(root):
7    count += len(filenames)
8
9print(count)

This loop counts every file name reported under root. If you want to skip directories such as __pycache__ or .git, prune dirnames inside the loop before descending further.

python
1import os
2
3root = "/tmp/example"
4count = 0
5
6for current_dir, dirnames, filenames in os.walk(root):
7    dirnames[:] = [name for name in dirnames if name != "__pycache__"]
8    count += len(filenames)
9
10print(count)

Validate The Path And Handle Errors

Filesystem code should be explicit about invalid paths. A missing directory and a directory that contains zero files are not the same result.

python
1from pathlib import Path
2
3def count_files(path_str: str) -> int:
4    path = Path(path_str)
5
6    if not path.exists():
7        raise FileNotFoundError(f"Directory not found: {path}")
8    if not path.is_dir():
9        raise NotADirectoryError(f"Not a directory: {path}")
10
11    return sum(1 for entry in path.iterdir() if entry.is_file())
12
13print(count_files("/tmp/example"))

If you are scanning user-controlled paths, consider how permission errors should behave. In some programs you want to stop immediately. In others you may want to log the issue and continue.

One subtle point is symbolic links. Path.is_file() follows symlinks by default, which may or may not match your intent. If you only want regular files physically located inside the directory tree, be explicit about that rule when you design the function.

For quick automation, documenting the choice is often enough. For more sensitive tooling, add tests around symlink behavior so the count does not surprise you later.

Common Pitfalls

  • Forgetting to define whether the count is shallow or recursive.
  • Counting directory entries without checking whether they are files.
  • Ignoring permission failures and treating them as a successful zero count.
  • Overlooking symlink behavior in recursive scans.
  • Building a full list of names when a streaming count is enough.

Summary

  • Use Path.iterdir() for a clean one-directory count.
  • Use os.scandir() when you want efficient top-level scanning.
  • Use rglob() or os.walk() when the count should include subdirectories.
  • Be explicit about missing paths, permission errors, filters, and symlink rules.

Course illustration
Course illustration

All Rights Reserved.