zlob: A glob library that spends less time on the filesystem

zlob pre-analyzes patterns, prunes dead branches early, and leans on Zig SIMD and direct syscalls to make file matching feel cheap again.

9 min read • View on GitHub • More from dmtrKovalenko

A directory tree drawn as a dense hedge maze, with several whole branches cut away before the path reaches them. One narrow path stays lit and leads to a small cluster of files, showing how the library avoids unnecessary filesystem work.
The core idea is simple: prove what cannot match before you start walking the tree.
Key Takeaways

Most glob libraries look boring until a toolchain, editor, or build step starts calling them thousands of times. Then every wasted directory read and every extra string pass shows up in the latency budget. zlob is interesting because it treats globbing like a search problem, not a pattern-matching problem.

The project starts by deciding what not to do

The core engine in src/pattern_context.zig turns incoming patterns into templates before it touches the disk. Common shapes like prefix matches, suffix matches, and simple extensions can take fast paths instead of falling through to heavier wildcard logic. That means the library can prune whole branches of the tree when the pattern makes them impossible.

This is the real shift. Traditional globbing often spends most of its time wandering through directories it will later discard. zlob tries to make that waste visible upfront, then remove it.

Pattern analysis happens before the walker commits to a full filesystem search, which is why the library can skip so much work.

Why Zig is the right kind of unusual

The choice of Zig is not cosmetic. The codebase leans on Zig's SIMD support so it can scan strings and separators quickly without turning the project into a pile of platform-specific intrinsics. In practice, that helps the matcher find the interesting bytes faster, and it keeps the implementation readable enough to stay portable.

On Linux, the walker can go lower than libc and use getdents64 directly. That cuts out some of the overhead that comes with standard directory enumeration, which matters when the library is crawling large trees. The result is a design that treats libc compatibility as an interface choice, not a performance ceiling.

Compatibility is the product, not the compromise

The public API mirrors the familiar glob_t shape, then extends it with extra data that FFI callers can use immediately. One example is zlo_pathlen, which carries path lengths alongside the strings so Rust or Zig consumers do not need to recompute strlen() for every result. That is a small change with a very specific payoff: less repeated work at the boundary.

Areaglibc glob(3)zlob
Pattern handlingClassic shell-style matching with limited modern conveniencesPre-analyzes patterns and promotes common cases to fast paths
Filesystem traversalRelies on standard directory iterationCan prune branches early and use direct syscalls on Linux
Modern syntaxBrace expansion and recursive patterns are not the main focusSupports recursive <code>**</code>, braces, extglob, and gitignore-style behavior
FFI surfaceReturns paths, leaving callers to do more workExtends the result set with path lengths for faster consumers

That table is the point. zlob is not trying to invent a new pattern language. It is trying to make the old one cheaper to use in real programs.

Where this matters

The obvious beneficiaries are compilers, linters, indexers, and anything else that spends a lot of time finding files. The less obvious ones are language bindings and embedded tools, where the FFI boundary can quietly dominate the cost of a seemingly simple directory scan. The repo's Rust wrapper and C header make that path practical, not theoretical.

That combination is what makes the project feel unusually complete. There is a fast inner loop, a compatibility layer for old callers, and enough structure around it to serve more than one language ecosystem. It is a small utility with infrastructure-level consequences.