directory iteration
file system
programming efficiency
code optimization
directory traversal

Which is the most efficient way to iterate a directory?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

The most efficient way to iterate a directory in Python is usually os.scandir(), especially when you need file-type checks or metadata. The reason is not magic syntax; it is that scandir exposes directory entries with cached information, which can avoid extra stat system calls that other approaches often trigger.

Why os.scandir() Is Usually the Fastest

os.listdir() returns plain file names. If you then ask whether each name is a file or directory, Python must often perform additional filesystem lookups.

os.scandir() returns DirEntry objects instead, and those objects can often answer questions such as:

  • 'is_file()'
  • 'is_dir()'
  • 'stat()'

more efficiently because the directory scan already provided some of that information.

Here is the basic pattern:

python
1import os
2
3with os.scandir(".") as entries:
4    for entry in entries:
5        print(entry.name, entry.is_file(), entry.is_dir())

For large directories, this difference is often substantial.

Compare It With os.listdir()

This older approach is still fine when you only need names:

python
1import os
2
3for name in os.listdir("."):
4    print(name)

But if you then do:

python
1import os
2
3for name in os.listdir("."):
4    path = os.path.join(".", name)
5    if os.path.isfile(path):
6        print("file:", name)

you may end up paying for one directory listing plus many extra metadata checks. That is exactly the workload where scandir tends to win.

Use pathlib for Readability, Not Raw Speed

pathlib.Path.iterdir() is a pleasant API:

python
1from pathlib import Path
2
3for path in Path(".").iterdir():
4    print(path.name)

It is often a good choice when readability matters, but the performance discussion is slightly different. pathlib is a higher-level abstraction. For many scripts it is fast enough, but when the question is strictly "most efficient," os.scandir() is the more direct performance-oriented answer.

That said, if your code is dominated by actual file processing rather than directory listing, the difference may be irrelevant.

For Recursive Traversal, Use os.walk()

If you need to recurse through subdirectories, os.walk() is usually the right tool:

python
1import os
2
3for root, dirs, files in os.walk("."):
4    for filename in files:
5        print(os.path.join(root, filename))

Modern Python implementations of os.walk() benefit from scandir internally, so you usually do not need to reimplement recursive traversal manually just for performance.

Choose the Tool Based on the Real Task

A practical guideline is:

  • use os.scandir() for efficient top-level directory iteration,
  • use os.walk() for recursive traversal,
  • use pathlib when clarity and path-oriented code are more valuable than squeezing the last bit of listing performance,
  • use os.listdir() only when you truly just want names and nothing else.

The fastest API is not always the best API if the surrounding code becomes harder to read for no meaningful benefit.

Lazy Iteration Matters

Another nice property of scandir is that it yields entries lazily:

python
1import os
2
3with os.scandir(".") as entries:
4    first_python_file = next(
5        (entry.name for entry in entries if entry.name.endswith(".py")),
6        None,
7    )
8
9print(first_python_file)

That means you can stop early without materializing an entire list first. For very large directories or short-circuit searches, that can matter as much as the metadata caching.

Benchmarking in Context

If you care deeply about speed, benchmark the actual workload. Directory iteration performance depends on:

  • local disk versus network filesystem,
  • number of entries,
  • whether you call stat,
  • and what you do with each result afterward.

A faster iterator does not matter much if your program spends almost all of its time opening, reading, and parsing the files after listing them.

Common Pitfalls

The biggest pitfall is using os.listdir() and then calling os.path.isfile() or os.stat() for every entry when os.scandir() would have been a better fit from the start.

Another mistake is optimizing the listing code when the real bottleneck is file I/O or downstream processing. Measure before assuming the directory iterator is the problem.

Developers also sometimes forget to close scandir iterators in long-running programs. Using with os.scandir(...) as entries: is the clean pattern.

Finally, do not force a low-level API everywhere if pathlib makes the code substantially clearer and the directory scan is not actually hot.

Summary

  • 'os.scandir() is usually the most efficient way to iterate a directory in Python.'
  • It outperforms os.listdir() when you also need file-type or metadata checks.
  • Use os.walk() for recursive traversal instead of hand-rolling directory recursion.
  • 'pathlib is often the nicest API, even if it is not the strict performance winner.'
  • Benchmark the full workload before over-optimizing directory iteration alone.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.