Skip to content
Select theme

How to create a directory and its parents

Short answer: fs::create_dir_all("demo/data/logs") creates every missing parent on the way down. fs::create_dir makes exactly one level and fails with NotFound if the parent isn’t there. Use create_dir_all unless you have a reason to want the failure.

From a fresh project — cargo new mkdir-demo, then replace the contents of src/main.rs with each block below and run it with cargo run. Each block builds what it needs from an empty directory, so it runs on its own and in any order. The remove_dir_all call at the top is a fixture; in real code the cleanup wouldn’t be there.

create_dir is mkdir: one new directory, and the error you get when its parent is missing:

created demo
entity not found: No such file or directory (os error 2)

demo is created, and the nested call fails with NotFound — “No such file or directory”, the same thing mkdir demo/data/logs says in a shell. There is no flag to ask for parents; the one-call version is a different function.

create_dir_all is mkdir -p. One call builds the path top-down, and the interesting part is what happens when you call it twice — it doesn’t complain:

created demo/data/logs
create_dir_all again: ok
entity already exists: File exists (os error 17)

The second create_dir_all returns Ok because the directory already exists — the standard library documents that as normal behaviour, not a special case you have to handle. create_dir on the same path gives AlreadyExists: “File exists (os error 17)”. This is the difference that matters in programs: setup code that runs on every start can call create_dir_all unconditionally and check the Result for real failures, no exists() check in front of it.

create_dir_all can’t do the impossible. If something that isn’t a directory is sitting in the path, it stops there:

not a directory: Not a directory (os error 20)

NotADirectory — the file demo/notes.txt would have to be a directory for archive to live under it. Unlike the missing-parent case this is a real conflict, not a call you should have made differently: something else created that path first, and the fix is in your program’s layout, not in the arguments.