File System Operations
Creating Directories
Rust provides two functions in std::fs (plus the std::fs::DirBuilder builder) for creating directories on the filesystem: std::fs::create_dir (single directory creation, analogous to mkdir) and std::fs::create_dir_all (recursive parent-and-leaf creation, analogous to mkdir -p).
Comparing create_dir, create_dir_all, and DirBuilder
| Function / Type | If Parent Directory Is Missing | If Target Directory Already Exists | Best Use Case |
|---|---|---|---|
fs::create_dir(path) |
Fails with ErrorKind::NotFound |
Fails with ErrorKind::AlreadyExists! |
Atomic directory lock acquisition or strict single-level creation |
fs::create_dir_all(path) |
Creates all missing parent directories recursively | Succeeds (Ok(())) if target is already a directory! |
Ensuring an output directory tree ("build/cache/v1") exists before writing files |
fs::DirBuilder::new() |
Configurable via .recursive(bool) |
Fails if non-recursive, succeeds if .recursive(true) |
Setting Unix octal permissions (DirBuilderExt::mode(0o700)) on newly created directories |
`fs::create_dir("a/b/c")` (When `"a"` does not exist):
---> Returns `Err(ErrorKind::NotFound)`!
`fs::create_dir_all("a/b/c")` (Idempotent `mkdir -p`):
---> Creates `"a"`, then `"a/b"`, then `"a/b/c"` (and succeeds if `"a/b/c"` already exists!)
use std::fs::{self, DirBuilder};
use std::io::{self, ErrorKind};
fn main() -> io::Result<()> {
let base = std::env::temp_dir().join("rust_ch50_mkdir_demo");
let nested = base.join("level1/level2");
let _ = fs::remove_dir_all(&base);
// 1. `create_dir` fails when intermediate parent `"level1"` is missing:
let err = fs::create_dir(&nested).unwrap_err();
println!("create_dir on missing parent: {:?}", err.kind());
// 2. `create_dir_all` creates all missing parents and is idempotent:
fs::create_dir_all(&nested)?;
fs::create_dir_all(&nested)?; // Second call succeeds with `Ok(())`!
println!("nested exists after create_dir_all: {}", fs::exists(&nested)?);
// 3. `create_dir` on an already existing directory returns `AlreadyExists`:
match fs::create_dir(&nested) {
Ok(()) => unreachable!(),
Err(e) if e.kind() == ErrorKind::AlreadyExists => {
println!("create_dir on existing dir: AlreadyExists");
}
Err(e) => return Err(e),
}
// 4. `DirBuilder` with custom options:
let custom_dir = base.join("custom");
let mut builder = DirBuilder::new();
builder.recursive(true);
#[cfg(unix)]
{
use std::os::unix::fs::DirBuilderExt;
builder.mode(0o700);
}
builder.create(&custom_dir)?;
fs::remove_dir_all(&base)?;
Ok(())
}
create_dir on missing parent: NotFound
nested exists after create_dir_all: true
create_dir on existing dir: AlreadyExists