Filehandles, files, directories
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
$_. 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#
rmdir FILENAME
rmdir
What you get back#
1 on success, 0 on failure (with $! set to the
errno from the failed system call). Unlike most I/O primitives
rmdir does not return 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.
rmdir $dir
or die "rmdir $dir failed: $!";
Global state it touches#
Examples#
Plain call, explicit directory:
rmdir "build/tmp"
or die "rmdir build/tmp: $!";
Default target. Inside while (readdir ...) or a loop that leaves the
name in $_:
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:
use Errno qw(ENOENT);
unless (rmdir $dir) {
die "rmdir $dir: $!" unless $! == ENOENT;
}
Remove a directory only after emptying it first:
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:
use File::Path qw(remove_tree);
remove_tree("build", { error => \my $err });
die "remove_tree: @$err" if @$err;
Edge cases#
Directory not empty:
$!is set toENOTEMPTYon most Unix systems (some BSDs useEEXIST). This is the single most commonrmdirfailure. List the directory contents or callremove_treeif recursive deletion is what you actually want.No argument:
rmdirwith no argument uses$_, not@ARGVand not the current directory. Writingrmdir()with empty parentheses is the same asrmdirwith no argument — it still reads$_.Symlink to a directory:
rmdirrefuses to remove symlinks; it operates on directories only. Useunlinkon the symlink itself.$!is typically set toENOTDIR.Current working directory: On Linux,
rmdir ".";usually fails withEBUSYorEINVALdepending on the filesystem. Do not rely on being able to remove the directory you are sitting in;chdirelsewhere first.Permissions: you need write + execute permission on the parent directory, not on the directory being removed. Removing
/a/b/cchecks/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; otherwiseEPERM.Trailing slash:
rmdir "foo/"works and means the same asrmdir "foo".Race with another process: between your
opendir/readdirloop and the finalrmdir, another process may create a file in the directory. You will then seeENOTEMPTYdespite 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— create a directory; the inverse operation, with the sameFILENAME-or-$_argument conventionunlink— remove files (and symlinks);rmdirremoves only empty directorieschdir— change the current working directory, often used beforermdirto avoid trying to remove the directory you are inopendir/readdir— list a directory’s contents before emptying and removing it$!— holds theerrnoof a failedrmdir; check forENOENT/ENOTEMPTY/EPERMto branch on the reason