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.
4 min read
In Python, Path.rglob("*") and glob.glob("**/*", recursive=True) are effectively the same speed for listing files: 5.95 ms vs 6.19 ms on a 1,210-file tree with Python 3.13.5, because both return directories too and pay for an is_file check on every hit. If raw speed matters, os.walk listed the same files in 1.30 ms (about 4.6x faster than rglob and 4.8x faster than glob), so use rglob for Path ergonomics and walk for bulk listing
Related links:
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.
| 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).
Script: lab-evidence/76-glob-vs-rglob-vs-walk/results/run_lab.py.
| 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 |
| 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.
os.walk wins listing — fewer Path object allocations; classic C-backed scandir walk.rglob ≈ glob for files after is_file filters (~1.04× modest).isfile checks dominate the files arms.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.
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().
Path.is_file() on every rglob hit without needing stat — expensive.| 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 |
Path.rglob(pattern) is Path.glob("**/" + pattern): it always searches recursively and returns Path objects. glob.glob needs "**" plus recursive=True and returns strings.
Not meaningfully. For files they were within about 1.04x on the 1,210-file tree (5.95 ms vs 6.19 ms) and similar on 4,170 files (22.52 ms vs 21.43 ms).
os.walk in this lab: 1.30 ms (~929k files/s) on 1,210 files and 4.57 ms on 4,170 files, because it already separates filenames from dirnames.
Evidence: /workspace/lab-evidence/76-glob-vs-rglob-vs-walk/results/ (+ fixture_tree/).
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
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/.
Explore the product
Untested by us. Check what's included, the license and refund terms before you buy.
Hands-on fnmatch.filter vs re.compile name-list filtering measured on Linux localhost.
Lab1 Oct 20264 min read
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.
Lab1 Oct 20264 min read
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.
Lab1 Oct 20264 min read