Plate 28
glob vs rglob vs os.walk: Listing Lab
Hands-on glob.glob vs Path.rglob vs os.walk lab: real files/s for recursive file listing on a modest fixture tree, measured on Linux localhost for SREs.
Aditya Challa4 min read
Intro — what this post promises
Need every file under a tree: is os.walk, pathlib.Path.rglob, or glob.glob(..., recursive=True) fastest? This lab builds a modest fixture tree on disk and reports wall time / files/s on Linux localhost.
Related links:
- pathlib vs os.path localhost lab
- shutil copyfile vs manual localhost lab
- json dumps compact vs indent localhost lab
- str translate vs replace localhost lab
- setdefault vs defaultdict localhost lab
- itertools chain vs flatten localhost lab
- hashlib md5 vs blake2b localhost lab
- perf_counter vs time localhost lab
Lab honesty (1 Oct 2026 IST): Python 3.13.5. Fixture at lab-evidence/76-glob-vs-rglob-vs-walk/fixture_tree/. Affiliates: 0. “Files” arms filter isfile / is_file(); “all” arms include directories.
Verdict up front (modest, 1,210 files): os.walk ~1.30 ms (~929k/s) vs rglob+is_file ~5.95 ms vs glob+isfile ~6.19 ms. Walk led glob by ~4.8× and rglob by ~4.6×. Prefer os.walk for raw listing speed; rglob for Path ergonomics.
Arms
| Arm | Pattern |
|---|---|
os.walk files | join dirpath+filenames |
os.walk count | len(filenames) only |
Path.rglob("*") | all entries / files filtered |
Path.glob("**/*") | equivalent glob on Path |
glob.glob("**/*", recursive=True) | stdlib glob + optional isfile |
Trees: modest (depth 2) and wider (depth 3).
Lab topology
Script: lab-evidence/76-glob-vs-rglob-vs-walk/results/run_lab.py.
Lead table — modest tree (p50)
| Arm | ms | entries/s |
|---|---|---|
| os.walk files | 1.30 | 929,424 |
| os.walk count-only | 1.55 | 782,611 |
| Path.rglob files | 5.95 | 203,484 |
| glob recursive files | 6.19 | 195,474 |
| Path.rglob all | 2.69 | 479,711 |
| glob recursive all | 2.33 | 552,566 |
Wider tree (4,170 files)
| Arm | ms | walk÷arm |
|---|---|---|
| os.walk files | 4.57 | 1.00× |
| Path.rglob files | 22.52 | 4.93× |
| glob recursive files | 21.43 | 4.69× |
Same ranking at larger scale: walk ~4.7× glob files.
Reading it
os.walkwins listing — fewer Path object allocations; classic C-backed scandir walk.rglob≈globfor files afteris_filefilters (~1.04× modest).- Filtering is costly — “all entries” glob/rglob is much closer to walk;
isfilechecks dominate the files arms. - Use Path when you need Path methods next; don’t pick rglob expecting a speedup over walk.
Fixture note
The tree is generated into evidence so you can re-list the same shape. It is not a kernel FS stress test — enough files to rank APIs, not millions of inodes.
Why isfile filters hurt
glob/rglob return directory entries too. Turning that into a file list means a metadata check per path. os.walk already separates dirnames from filenames, so the files arm mostly pays string joins. If you only need counts or names inside each directory, stay on walk and avoid a second pass of Path.is_file().
Pitfalls
- Comparing glob-all to walk-files — different entry sets (dirs included).
- Calling
Path.is_file()on every rglob hit without needing stat — expensive. - Assuming recursive glob is “free” — pattern matching + filters add up.
- Network FS / huge trees — re-measure; locality matters.
When to pick what
| Need | Prefer |
|---|---|
| Fast file list | os.walk |
| Path objects / suffixes | Path.rglob |
| Simple pattern string | glob.glob(..., recursive=True) |
| Count only | walk without building a giant list |
Reproduce
Evidence: /workspace/lab-evidence/76-glob-vs-rglob-vs-walk/results/ (+ fixture_tree/).
Closing
Walk to list; Path to ergonomics. On this box modest walk hit ~929k files/s, about ~4.8× glob+isfile and ~4.6× rglob+is_file. Reach for recursive glob when the pattern is the product; reach for walk when the product is “all files under here, fast.”
Lab evidence
What I found running this
Lab 1 Oct 2026 IST. Python 3.13.5. modest (1210 files): os.walk 1.30ms / 929k/s; rglob-files 5.95ms; glob-files 6.19ms (walk~4.8x glob, ~4.6x rglob). Affiliates: 0. Evidence: lab-evidence/76-glob-vs-rglob-vs-walk/.
Related links
Plate 18
fnmatch vs re Name Filter: Localhost Lab
Hands-on fnmatch.filter vs re.compile name-list filtering measured on Linux localhost.
Observability & SRE · 30 Sept 2026
Plate 84
tarfile vs zipfile Create+Extract: Localhost Lab
Hands-on tarfile vs zipfile create+extract lab: real MB/s on a mixed small-file fixture (uncompressed tar vs zip), measured on Linux localhost for SREs.
Observability & SRE · 30 Sept 2026
Plate 85
scandir vs listdir vs iterdir: Localhost Lab
Hands-on os.scandir vs listdir vs Path.iterdir lab: real entries/s for names and is_file on a synthetic tree, measured on Linux localhost (lab) for SREs.
Observability & SRE · 30 Sept 2026