--- name: rmdir signature: 'rmdir FILENAME' since: 5.0 status: documented categories: ["Filehandles, files, directories"] --- ```{index} single: rmdir; Perl built-in ``` *[Filehandles, files, directories](../perlfunc-by-category)* # rmdir Remove an empty directory. `rmdir` asks the operating system to delete the directory named by `FILENAME`. The directory must be empty — it must contain no entries other than `.` and `..`. If `FILENAME` is omitted, `rmdir` operates on [`$_`](../perlvar). This is a thin wrapper over the `rmdir(2)` system call and carries all of its restrictions: you cannot remove a non-empty directory, you cannot remove a directory you lack write permission on the parent of, and on most systems you cannot remove your current working directory. ## Synopsis ```perl rmdir FILENAME rmdir ``` ## What you get back `1` on success, `0` on failure (with [`$!`](../perlvar) set to the `errno` from the failed system call). Unlike most I/O primitives `rmdir` does not return [`undef`](undef) on failure — it returns the integer `0`, so the common test `rmdir $dir or die $!` still works because `0` is false. Always check the return value. A failed `rmdir` is silent otherwise; the next line of code will happily proceed as if the directory had been removed. ```perl rmdir $dir or die "rmdir $dir failed: $!"; ``` ## Global state it touches - [`$_`](../perlvar) — used as `FILENAME` when no argument is given. - [`$!`](../perlvar) — set to the `errno` of the failed `rmdir(2)` call on failure; left untouched on success. Read it immediately; any intervening system call may overwrite it. ## Examples Plain call, explicit directory: ```perl rmdir "build/tmp" or die "rmdir build/tmp: $!"; ``` Default target. Inside `while (readdir ...)` or a loop that leaves the name in [`$_`](../perlvar): ```perl for (@empty_dirs) { rmdir or warn "rmdir $_: $!"; } ``` Distinguish "already gone" from a real error. `ENOENT` means the directory does not exist, which is often fine for cleanup code: ```perl use Errno qw(ENOENT); unless (rmdir $dir) { die "rmdir $dir: $!" unless $! == ENOENT; } ``` Remove a directory only after emptying it first: ```perl opendir my $dh, $dir or die "opendir $dir: $!"; while (my $entry = readdir $dh) { next if $entry eq '.' or $entry eq '..'; unlink "$dir/$entry" or die "unlink $dir/$entry: $!"; } closedir $dh; rmdir $dir or die "rmdir $dir: $!"; ``` Recursive removal is **not** `rmdir`'s job. Use `File::Path`'s `remove_tree` — it walks the tree and deletes entries bottom-up: ```perl use File::Path qw(remove_tree); remove_tree("build", { error => \my $err }); die "remove_tree: @$err" if @$err; ``` ## Edge cases - **Directory not empty**: [`$!`](../perlvar) is set to `ENOTEMPTY` on most Unix systems (some BSDs use `EEXIST`). This is the single most common `rmdir` failure. List the directory contents or call `remove_tree` if recursive deletion is what you actually want. - **No argument**: `rmdir` with no argument uses [`$_`](../perlvar), not `@ARGV` and not the current directory. Writing `rmdir()` with empty parentheses is the same as `rmdir` with no argument — it still reads [`$_`](../perlvar). - **Symlink to a directory**: `rmdir` refuses to remove symlinks; it operates on directories only. Use [`unlink`](unlink) on the symlink itself. [`$!`](../perlvar) is typically set to `ENOTDIR`. - **Current working directory**: On Linux, `rmdir ".";` usually fails with `EBUSY` or `EINVAL` depending on the filesystem. Do not rely on being able to remove the directory you are sitting in; [`chdir`](chdir) elsewhere first. - **Permissions**: you need write + execute permission on the **parent** directory, not on the directory being removed. Removing `/a/b/c` checks `/a/b`'s mode, not `/a/b/c`'s. - **Sticky-bit parent** (e.g. `/tmp`): you also need to own the directory being removed or own the parent; otherwise `EPERM`. - **Trailing slash**: `rmdir "foo/"` works and means the same as `rmdir "foo"`. - **Race with another process**: between your `opendir`/`readdir` loop and the final `rmdir`, another process may create a file in the directory. You will then see `ENOTEMPTY` despite having just emptied it. Retry or fail loudly — do not silently ignore. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`mkdir`](mkdir) — create a directory; the inverse operation, with the same `FILENAME`-or-[`$_`](../perlvar) argument convention - [`unlink`](unlink) — remove **files** (and symlinks); `rmdir` removes only empty directories - [`chdir`](chdir) — change the current working directory, often used before `rmdir` to avoid trying to remove the directory you are in - [`opendir`](opendir) / [`readdir`](readdir) — list a directory's contents before emptying and removing it - [`$!`](../perlvar) — holds the `errno` of a failed `rmdir`; check for `ENOENT` / `ENOTEMPTY` / `EPERM` to branch on the reason