is_executable
A tiny Rust crate that checks whether a path points to an executable file, across Unix, Windows, and WASM.
Repository Health
Technical Analysis
is_executable is a small, focused Rust crate that answers one question: does the file at a given path exist and can it be executed? On Unix it checks the file’s permission bits directly via std::fs::Metadata; on Windows it falls back to matching the PATHEXT environment variable against the file’s extension, and if that’s inconclusive, calls into the Win32 GetBinaryTypeW API to inspect the binary header itself. On WASI and other WASM targets, where the concept of executable permission bits doesn’t apply the same way, it always returns false rather than guessing.
The crate exposes two equivalent ways to call it: a standalone is_executable(path) function that accepts anything implementing AsRef<Path>, and an IsExecutable extension trait that adds an .is_executable() method directly onto std::path::Path. Both compile down to the same platform-specific implementation selected via #[cfg(...)] attributes at build time, so there’s no runtime branching cost.
It’s the kind of dependency that shows up deep in the tree of larger tools — shell implementations, build systems, PATH-searching utilities, script runners — anywhere code needs to answer “can I run this file?” without shelling out or reimplementing OS-specific permission logic by hand. The crate is explicit that it does not protect against time-of-check to time-of-use (TOCTOU) races: the file’s executable status can change between the check and any subsequent attempt to run it, so callers needing atomicity should not treat this as a security guarantee.
What You Get
- A standalone
is_executable(path)function accepting anyAsRef<Path> - An
IsExecutableextension trait adding.is_executable()directly tostd::path::Path - Unix support via permission-bit inspection (
mode & 0o111) - Windows support via
PATHEXTextension matching with aGetBinaryTypeWfallback - Safe, deterministic
falseresults on WASI/WASM targets where the check doesn’t apply - Zero required dependencies on non-Windows platforms (only
windows-syson Windows)
Common Use Cases
- Searching
PATHdirectories to resolve a shell command to a runnable binary - Validating user-supplied script or binary paths before attempting to spawn them
- Filtering directory listings down to runnable files in a file manager or launcher
- Build tools and task runners deciding whether a discovered file can be invoked as a step
Under The Hood
Architecture
The crate is a single src/lib.rs file organized around one public extension trait, IsExecutable, with three mutually-exclusive #[cfg(...)]-gated implementations selected at compile time: a unix module using std::os::unix::fs::PermissionsExt, a windows module calling into the Win32 API via the windows-sys crate, and a wasm module that always returns false for WASI/WASM targets. A free-standing is_executable() function is a thin wrapper that forwards to the trait method, so both call styles compile to identical generated code. There is no runtime dispatch, no allocation beyond what the OS calls require, and no internal state — the entire abstraction is a single boolean-returning predicate resolved per-platform by the compiler, so there’s nothing to break beyond swapping in a new target’s implementation module.
Tech Stack
Pure Rust with edition 2021, targeting std::path::Path and std::fs::Metadata on Unix, windows-sys (pinned >=0.59, <=0.61 with only the Win32_Storage_FileSystem feature) on Windows, and no additional runtime dependencies on WASI/WASM. The only dev-dependency is diff for test assertions. There is no build step beyond cargo build/cargo test; the crate ships as a docs.rs-published library with its README embedded directly into the crate documentation via #![doc = include_str!("../README.md")].
Code Quality
tests/tests.rs covers each platform branch with #[cfg(...)]-gated test modules — Unix tests check regular files, symlinks (executable and non-executable), and directories; Windows tests check a known system binary and extension-based detection; WASM tests assert the always-false behavior — plus shared tests for nonexistent paths. CI (.github/workflows/ci.yml) runs the full suite across ubuntu-latest, macos-latest, and windows-latest on stable Rust, plus beta, nightly, and a pinned MSRV of 1.80.0 on Ubuntu, and a separate WASI job targeting wasm32-wasip2 under Wasmtime. Error handling is minimal by design — the API surface is a single infallible boolean predicate that swallows Metadata errors into false rather than propagating a Result, which is a deliberate ergonomic tradeoff for a helper this small.
API Design
The crate offers two equally ergonomic entry points to the same behavior — a free function for callers who prefer explicit calls, and an extension trait for callers who want .is_executable() to read naturally on a Path value — with no configuration, no builder pattern, and no required setup beyond the import. Documentation is thorough for the crate’s size: the module-level docs (reused as the README) include working code samples for both API styles, and the crate explicitly documents its TOCTOU limitation rather than leaving it implicit. The result is close to zero-boilerplate adoption: one use statement and a single method or function call.