π Overview
walkdir_minimal is a lightweight, POSIX-only directory walker written in
100% safe Rust, designed for maximum portability, robust error handling,
and predictable iteration order across UNIX-like systems.
Unlike the popular walkdir crate, which
offers extensive configurability and Windows support, walkdir_minimal aims to
provide a clean, dependency-free and fully deterministic implementation
that follows the UNIX filesystem model precisely β no abstractions, no hidden
buffering, no non-POSIX extensions.
β¨ Key Features
-
π§± POSIX-only: Works on Linux, FreeBSD, OpenBSD, NetBSD, and Solaris.
-
βοΈ No dependencies: Implemented using only
std::fs,std::path, and minimal data structures. -
𦦠Lightweight and predictable: The walker uses a manual stack (no recursion), allowing predictable memory and performance behavior.
-
π¦ Configurable options via
WalkOptions:follow_links: whether to follow symbolic links to directories.max_depth: optional limit on traversal depth.
-
π§ Cycle detection: Detects and prevents infinite loops caused by symbolic links that form cycles.
-
π« Graceful handling of I/O errors: Broken symlinks, permission-denied directories, and other errors are returned as
Err(WalkError::Io). -
𦦠Filtering: Supports entry-level filtering with a user-provided closure.
-
π§« Deterministic: The order of traversal follows the order provided by the filesystemβs
readdir(3)implementation β consistent across runs on the same system. -
π§ͺ Minimal yet robust: Designed for projects that require reliable, low-level control rather than high-level abstraction.
πͺΆ Design Philosophy
walkdir_minimal is built under the following principles:
- POSIX compliance first β all filesystem operations map directly to their POSIX
equivalents (
lstat,stat,opendir,readdir, etc., via Rustβsstd::fs). - Deterministic behavior β the iterator never hides errors, skips entries silently, or spawns threads.
- No allocations beyond whatβs necessary β uses
Vecfor the manual stack andHashSetfor visited inode/device pairs (loop detection). - No recursion β prevents stack overflows and maintains stable memory usage even for deeply nested trees.
- Minimalism β the crate is intentionally limited to features that can be reasoned about and verified easily.
- Transparency β the API surfaces raw I/O results instead of silently ignoring or swallowing them.
walkdir_minimal embodies clarity over complexity. Its goal is not to compete
with feature-rich crates, but to provide a clean reference implementation
of a POSIX-only directory walker.
βοΈ Comparison with walkdir
| Feature | walkdir |
walkdir_minimal |
|---|---|---|
| Cross-platform | β (Windows, macOS, Linux) | β POSIX only |
| Dependencies | Many (e.g., same-file, winapi) | β None |
| Error handling | Complex iterator states | Simple Result<Entry, WalkError> |
| Loop detection | Optional, platform-specific | Deterministic (dev, ino) hashing |
| Symbolic links | Optional follow | Optional follow |
| Custom sorting | Supported | Not supported (filesystem order only) |
| Performance | Optimized for general use | Optimized for predictability |
| Safety | 100% safe Rust | 100% safe Rust |
| Recursion | Implicit | Manual stack |
| Binary size | Larger | Tiny |
| Filter API | Supported (filter_entry) |
Supported |
| Error type | walkdir::Error |
WalkError |
| Metadata caching | Yes | No (on-demand) |
| Thread safety | Yes | No (intentionally minimal) |
π¦ Example Usage
use ;
Output example:
.
./src
./src/lib.rs
./src/entry.rs
./src/error.rs
./src/walkdir.rs
π¦ WalkOptions
-
follow_linksβ Whentrue, symbolic links to directories are followed. -
max_depthβ Optional limit to recursion depth.Nonemeans unlimited.- The root is always depth
0. - Files or subdirectories at one level below are depth
1, and so on.
- The root is always depth
π Entry API
metadata()callsfs::metadata, following symlinks.symlink_metadata()callsfs::symlink_metadata, not following symlinks.file_type()reports the symbolic link type correctly.
π¦ Error Handling
-
Io(io::Error)β Covers all I/O-related errors, including:- Broken symbolic links (
ENOENT) - Permission-denied directories (
EACCES) - Filesystem read errors
- Broken symbolic links (
-
LoopDetected(PathBuf)β Reported when a cyclic symbolic link is detected (only if loop detection is enabled).
βοΈ Default Behavior Summary
| Case | Behavior |
|---|---|
| Broken symlink | Yields Err(WalkError::Io) |
| Permission denied directory | Yields Err(WalkError::Io) and continues |
| Loop via symlink | Yields Err(WalkError::LoopDetected) if detection is on |
| Regular file as root | Returns file directly, no traversal |
| Unreadable entry | Returns Err(WalkError::Io) |
Exceeds max_depth |
Skips entry silently (depth-guarded) |
π Technical Details
π Core Design
walkdir_minimal implements a depth-first directory traversal without relying on
any external dependencies, using only POSIX APIs available through Rustβs standard
library. The iterator is built around a manual stack-based traversal that mimics
recursion, avoiding stack overflows for deeply nested directories.
- Stack-based iteration: Uses an internal vector of
StackEntrystructs, each holding an activeReadDirhandle and its depth. - Loop detection: Uses a
HashSet<(dev, ino)>to detect and skip cyclic symlinks, preventing infinite recursion. - Filter callbacks: Optional user-provided closures (
filter_entry) allow pruning of the traversal tree dynamically. - Error resilience: Each I/O operation is wrapped in
Result, and errors are surfaced asWalkErrorvariants (Io,LoopDetected).
π Error Handling Philosophy
walkdir_minimal follows a fail-soft philosophy:
- Broken symlinks are returned as
Ok(Entry)unless metadata is explicitly requested. - Directories without permission to read (
EACCES) return anErr(WalkError::Io), allowing iteration to continue with the next entry. - Files disappearing mid-iteration yield
Err(WalkError::Io)gracefully.
This mirrors walkdirβs behavior but keeps it predictable and minimal.
π Metadata Access
Entry deliberately does not cache metadata by default. This ensures:
- Minimal memory overhead.
- Consistent behavior with file system changes.
- Full control for users who may wish to query
metadata()orsymlink_metadata()selectively.
let entry = new;
if let Ok = entry.metadata
π Platform Scope
walkdir_minimal targets POSIX systems only β this includes:
- GNU/Linux
- *BSD family (FreeBSD, OpenBSD, NetBSD, DragonFly)
- Solaris and Illumos
It relies on MetadataExt for device/inode access, which is non-portable
to Windows. No attempt is made to support non-POSIX environments.
π Performance Characteristics
- Single
ReadDirhandle open at a time per stack frame. - Minimal heap allocations aside from the stack and visited set.
- No synchronization primitives β designed for single-threaded deterministic traversal.
- Filtering and loop detection incur negligible overhead for typical file trees.
π Safety & Reliability
- No unsafe code.
- Uses standard library types exclusively (
HashSet,Vec,ReadDir, etc.). - All system calls are wrapped in safe Rust abstractions.
- Loop detection ensures full reliability even on pathological file systems.
π Practical Use Cases
- Static analysis tools.
- POSIX-friendly installers and archivers.
- File packers and dependency scanners.
- System recovery tools that must run without external crates.
Example: skipping hidden files and following symlinks safely:
use WalkDir;
let iter = new
.unwrap
.follow_links
.filter_entry;
for entry in iter
π‘ Why Choose walkdir_minimal?
- Ideal for small binaries, system utilities, and initramfs tools.
- Zero build dependencies (fast compile times).
- Deterministic and predictable traversal order.
- Designed to be readable and hackable.
π§© Implementation Notes
- Loop detection uses
(dev, ino)pairs to identify unique directories. - When
follow_linksis disabled, symlink loops are naturally impossible. max_depthlimits traversal, excluding deeper entries.- The iterator yields entries as soon as they are discovered β no preloading or buffering.
π€ Contributing
Contributions are very welcome! Whether itβs fixing a bug, improving documentation, or adding new features that align with the minimalist and POSIX-only philosophy, your input is appreciated.
Please follow these guidelines when contributing:
- Keep it minimal β avoid adding dependencies or non-POSIX abstractions.
- Preserve safety β no
unsafecode will be accepted. - Document behavior clearly β especially for error cases and edge conditions.
- Add tests β every feature or bug fix should include a minimal test.
If you find a bug or have a suggestion for improvement:
- Open an issue describing the behavior or proposal clearly.
- Include steps to reproduce (for bugs) or examples (for feature requests).
Pull requests should target the main branch and include clear commit messages.
π§ͺ Testing
walkdir_minimal includes tests for common scenarios:
- Regular files and nested directories.
- Symbolic link loops and detection.
- Permission-denied directories.
- Broken symbolic links.
- Filtered traversals and depth limits.
Run the test suite with:
π§± Project Structure
walkdir_minimal/
βββ src/
β βββ lib.rs # Main crate entry
β βββ entry.rs # Defines the Entry type
β βββ error.rs # WalkError and error utilities
β βββ options.rs # WalkOptions definition
β βββ tests.rs # Unit and integration tests
β βββ walkdir.rs # Core iterator implementation
βββ README.md # Project documentation
βββ LICENSE # License file (MIT)
βββ Cargo.toml # Package metadata
π MIT License
This repository has scripts that were created to be free software. Therefore, they can be distributed and/or modified within the terms of the MIT License.
See the LICENSE file for details.
π¬ Contact & Support
- π§ Email: m10ferrari1200@gmail.com
- π§ Email: contatolinuxdicaspro@gmail.com