269. DirEntry::file_type — Stop Paying a stat() Per Entry
Filtering read_dir entries with path.is_file() costs a full metadata lookup per entry — and quietly reports false when the check fails. DirEntry::file_type() is free on most platforms and tells you when it couldn’t answer.
This morning’s bite 268 collected read_dir entries into paths. The next thing most code does is filter them, and the obvious way has two hidden problems:
| |
First, Path::is_file() asks the filesystem for full metadata — an extra syscall for every entry, on top of the directory read that already happened. Second, it returns plain bool: if the metadata lookup fails (permissions, a file deleted mid-loop), you get false, indistinguishable from “this is a directory”. Errors vanish.
The entry you already have knows its own type:
| |
Two things improved:
- no extra syscall — on Linux,
readdirreturns each entry’s type alongside its name (d_type), and Windows directory entries carry file attributes.file_type()just hands you what the directory read already produced. (A few filesystems don’t filld_typein; std falls back to a metadata call only then.) - errors surface —
file_type()returnsio::Result<FileType>, so a failed lookup is a?-able error instead of a silentfalse
One behavioral difference to know: file_type() does not follow symlinks — a symlink to a file reports is_symlink(), not is_file(), while Path::is_file() traverses the link and reports on the target. If following symlinks is what you actually want, that’s the one case for fs::metadata(entry.path()) — deliberately, not by accident.