Skip to content
Select theme

How to delete a file or a whole directory

Short answer: fs::remove_file("path") deletes one file. fs::remove_dir("path") deletes a directory — but only while it’s empty. fs::remove_dir_all("path") deletes a directory and everything inside it. All three return io::Result, and none of them ask for confirmation: there’s no recycle bin in the standard library, and what’s gone stays gone.

From a fresh project — cargo new delete-demo, then replace the contents of src/main.rs with each block below and run it with cargo run. Each block creates the files and directories it works on, so it runs on its own and in any order. Paths are relative to the directory you run from, which under cargo run is the project root.

still there: false

Deleting is unlinking: the name disappears from its directory. The path has to be a file — fs::remove_file on a directory is an error too (on this machine, Operation not permitted (os error 1); the exact wording is platform-specific). Directories get their own functions below.

nothing to delete: No such file or directory (os error 2)

NotFound is the one kind you can read backwards from: the standard library promises that a NotFound error means the path didn’t exist. The reverse doesn’t hold — an existing path can still fail to delete because of permissions — so this match means “there was nothing to do”, not “everything went fine”.

If you’re about to add an existence check before deleting: the check and the delete can race, and you end up handling NotFound anyway. Matching the error costs one branch and has no gap. The next page is about checking paths, so it stops there.

Directories: remove_dir and remove_dir_all

Section titled “Directories: remove_dir and remove_dir_all”
remove_dir refused: Directory not empty (os error 66)
still there: false

fs::remove_dir is the directory counterpart of remove_file, and it refuses anything non-empty — its error kind is DirectoryNotEmpty. The message and the error number are platform-specific; the kind isn’t. fs::remove_dir_all removes the directory and everything under it, files and subdirectories alike, so the usual rm -rf warning applies: it will happily delete a tree you pointed at by mistake. A path that doesn’t exist is a NotFound error for both functions, same as for remove_file.

Nothing here goes to a recycle bin. No confirmation, no undo, and no standard-library way back.

One subtlety is visible on Unix, where deletion really is just an unlink:

name gone: true
handle still reads: "still being read\n"

The name is gone, but the handle opened before the delete still reads the contents. On Unix the data isn’t released until the last name and the last handle are gone. The standard library only promises this loosely — there’s “no guarantee that the file is immediately deleted”, because on some platforms other open file descriptors prevent immediate removal — so when the disk space actually comes back is a platform question, not a Rust one.

If the deletion needs to be recoverable, don’t use remove_file: move the file into the user’s trash instead. The standard library can’t do that, so it means a third-party crate.