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