path-extra
Extra methods on Path for ergonomic and chainable fs operations.
Stop juggling fs functions, start chaining Path methods.
Supports std (default) and tokio (feature flag).
Problem
The standard library scatters file system operations across std::fs as free functions:
// Path is always the odd one out
let config_file = config_dir.join;
create_dir_all?;
write?;
set_permissions?;
Solution
With PathExt, file system operations are now where they belong — on the Path itself:
use PathExt as _;
// Path stays in focus and chains naturally
config_dir.create_dir_all?
.join
.write?
.set_permissions?;
Installation
# Supports std by default
cargo add path-extra
# To enable Tokio support
cargo add path-extra --features=tokio
Features
Method chaining
Operations on the same Path compose elegantly into a single expression:
let metadata = config_file.metadata?;
// Atomic file update
config_file.with_extension
.write_new?
.set_permissions?
.rename?;
Graceful NotFound / AlreadyExists
Use ergonomic _if_exists / _if_not_exists variants to deal with Ok(None) instead:
// Before: Tedious and easy to get wrong
let config = match read ;
// After: Intent is clear, noise is gone
let config = config_file.read_if_exists?.unwrap_or;
use ;
// Idempotent file creation
config_dir
.create_dir_all?
.join
.write_new_if_not_exists?
.set_permissions?;
Symlink flavors
target.symlink?; // Store target as-is
target.symlink_absolute?; // Resolve target to absolute
target.symlink_relative?; // Compute relative target from link parent
Atomic linking
target.symlink_atomic?;
target.symlink_absolute_atomic?;
target.symlink_relative_atomic?;
target.hard_link_atomic?;
Symlink-aware checks
Both .exists() and .try_exists() don't work with broken symlinks:
// Before: Broken symlink
broken.exists // false
broken.try_exists? // false
// After: See the symlink itself
broken.exists_nofollow // true
broken.try_exists_nofollow? // true
The following _nofollow variants are also provided for convenience:
// Infallible — Return false on error like .exists()
path.exists_nofollow
path.is_file_nofollow
path.is_dir_nofollow
// Fallible — Propagate errors just like .try_exists()
path.try_exists_nofollow
path.try_is_file_nofollow
path.try_is_dir_nofollow
Tokio
The standard Path only has sync methods, using the wrong ones will block your async runtime.
Enable the tokio feature flag and PathExt gives you async methods directly on Path:
use PathExt as _;
let metadata = config_file.metadata_async.await?;
config_file.with_extension
.write_new.await?
.set_permissions.await?
.rename.await?;
Import AsyncPathExt to chain the entire expression and .await only once at the end:
use ;
config_file.with_extension
.write_new
.set_permissions
.rename
.await?;
Both OptionPathExt and AsyncOptionPathExt are available under tokio as well.