I/O

closedir#

Close a directory handle opened by opendir.

closedir releases the operating-system directory stream associated with DIRHANDLE and frees the slot so the handle can be reused. It is the counterpart to opendir, and the only supported way to close a directory handle — close operates on file handles and does not accept a directory handle, because file handles and directory handles live in separate namespaces.

Synopsis#

closedir DIRHANDLE
closedir $dh

What you get back#

1 on success, undef on failure (with $! set to the error from the underlying closedir(3) call). The return value is worth checking on networked or FUSE-backed filesystems where the close may surface a deferred I/O error.

closedir $dh
    or warn "closedir $path failed: $!";

Closing a directory handle that is already closed, or one that was never successfully opened, returns undef and — under use warnings — emits a closedir() attempted on invalid dirhandle warning.

Lexical directory handles and auto-close#

A directory handle stored in a lexical scalar — the form produced by opendir my $dh, $path — is closed automatically when the scalar goes out of scope (or is reassigned, or the program exits). Explicit closedir is then a matter of timing, not correctness:

sub entries {
    my ($path) = @_;
    opendir my $dh, $path or die "opendir $path: $!";
    return readdir $dh;
    # $dh is closed here as it leaves scope
}

Call closedir explicitly when you need the release to happen at a known point — before forking, before renaming the directory on platforms that hold it open, before checking the return value, or simply when the enclosing scope is long and holds many other resources.

Bareword directory handles (package globals, e.g. opendir DH, $path) are not auto-closed. They persist until the program ends or closedir DH is called.

Global state it touches#

closedir does not read or write any of Perl’s documented special variables. It sets $! on failure. It does not affect $_, the selected filehandle, or any of the output-separator globals.

Examples#

Basic open/read/close cycle:

opendir my $dh, "." or die "opendir: $!";
my @names = readdir $dh;
closedir $dh;

Check the return value — useful on network filesystems:

opendir my $dh, "/mnt/nfs/project" or die "opendir: $!";
my @entries = readdir $dh;
closedir $dh
    or die "closedir failed: $!";

Reset to the start with rewinddir instead of closedir + opendir when you want to re-read the same directory:

opendir my $dh, $path or die $!;
my @first = readdir $dh;
rewinddir $dh;
my @again = readdir $dh;             # same set as @first
closedir $dh;

Bareword handle — must be closed explicitly:

opendir DH, "/etc" or die $!;
while (my $name = readdir DH) {
    last if $name eq "hosts";
}
closedir DH;                         # not optional for barewords

Using close on a directory handle does not work:

opendir my $dh, "." or die $!;
close $dh;                           # wrong — does not close the dir
closedir $dh;                        # correct

Edge cases#

  • close on a directory handle: file handles and directory handles are distinct types. close on a directory handle is either a no-op or an error depending on the handle form; always use closedir to close what opendir opened.

  • Double close: calling closedir twice on the same handle returns undef on the second call and sets $!. Under use warnings a closedir() attempted on invalid dirhandle warning is emitted.

  • Closed or never-opened handle: same behaviour as double close — undef return and a warning under use warnings.

  • Pending readdir state: closedir discards any unread entries. If you want to restart iteration, use rewinddir instead of close + reopen.

  • seekdir / telldir positions: positions obtained from telldir are invalidated by closedir. They are only meaningful for the lifetime of a single open directory stream.

  • Scope exit during exception: lexical directory handles are still closed when the scope unwinds via die, so explicit closedir in cleanup code is usually redundant.

  • Fork: after fork, both parent and child share the directory stream’s kernel state; each should call closedir in whichever process no longer needs it.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • opendir — open a directory handle; closedir is its counterpart

  • readdir — read the next entry (or all entries in list context) from an open directory handle

  • rewinddir — reset the directory stream to the beginning without closing it

  • seekdir — reposition the directory stream to a value previously returned by telldir

  • telldir — return the current position within an open directory stream

  • close — close a file handle; does not work on directory handles