W3docs

readdir()

As developers, we know that directory handling is a critical aspect of any project, and that's where readdir() comes in. This PHP function allows you to read

The PHP readdir() function reads one entry at a time from a directory that you have already opened with opendir(). Each call returns the name of the next file or subdirectory and advances an internal pointer, so calling it in a loop lets you walk through every item in a folder. This page explains the syntax, the return value, the loop pattern that catches a common bug, and how readdir() compares to higher-level alternatives.

Syntax

readdir(resource $dir_handle = null): string|false
  • $dir_handle — a directory handle returned by opendir(). If you omit it, PHP uses the last handle opened by opendir().
  • Return value — the filename of the next entry as a string, or false when there are no more entries. The entries include the special . (current directory) and .. (parent directory) names, and they are returned in the order the filesystem stores them, not sorted.

Reading a directory

To use readdir(), first open a directory handle with opendir(), loop with readdir() until it returns false, then release the handle with closedir():

<?php

$dir = __DIR__; // the directory this script lives in

if ($handle = opendir($dir)) {
    while (false !== ($entry = readdir($handle))) {
        if ($entry !== "." && $entry !== "..") {
            echo "$entry\n";
        }
    }
    closedir($handle);
}

This opens the directory, iterates through its contents, and prints every name except . and ... The closedir() call frees the handle when you are done.

Why false !== and not just a truthy check

The strict comparison false !== ($entry = readdir($handle)) is essential, not stylistic. A directory can legitimately contain an entry named "0", and an empty-string check would also misbehave. PHP treats the string "0" as falsy, so writing while ($entry = readdir($handle)) would stop the loop early the moment it reached such a file. Comparing strictly against false makes the loop end only when readdir() actually runs out of entries.

Filtering entries by extension

readdir() returns raw names, so any filtering is up to you. Combine it with pathinfo() to keep only the file types you care about — here, images:

<?php

$dir = __DIR__;
$allowed = ['jpg', 'jpeg', 'png', 'gif'];

if ($handle = opendir($dir)) {
    while (false !== ($entry = readdir($handle))) {
        $extension = strtolower(pathinfo($entry, PATHINFO_EXTENSION));
        if ($entry !== "." && $entry !== ".." && in_array($extension, $allowed, true)) {
            echo "$entry\n";
        }
    }
    closedir($handle);
}

pathinfo($entry, PATHINFO_EXTENSION) pulls the extension off each name, and in_array(..., true) (strict mode) checks it against the allow-list so only matching files are printed.

Re-reading the same directory

Because each readdir() call advances the internal pointer, a second loop over the same handle returns nothing — the pointer is already at the end. Use rewinddir() to reset it to the first entry without reopening the directory:

<?php

$handle = opendir(__DIR__);

while (false !== ($entry = readdir($handle))) { /* first pass */ }

rewinddir($handle); // back to the start

while (false !== ($entry = readdir($handle))) {
    // second pass sees every entry again
}

closedir($handle);

readdir() vs scandir() vs glob()

readdir() is the low-level building block. In most modern code you reach for a one-call alternative instead:

  • scandir() returns all entries as a sorted array in a single call — no opendir/closedir bookkeeping.
  • glob() matches a shell-style pattern (for example *.png) and returns full paths, which makes extension filtering a one-liner.

Reach for readdir() when you want to process entries one at a time without loading the whole listing into memory (useful for very large directories), or when you need fine-grained control over the iteration.

Common gotchas

  • Always skip . and ..readdir() includes them, and forgetting to filter them out is the most frequent bug, especially in recursive directory walks.
  • opendir() can fail. If the path does not exist or is not readable it returns false and emits a warning, which is why the examples guard the loop with if ($handle = opendir($dir)).
  • Close your handles. Call closedir() (or let the script end) to release the resource.
  • Order is not guaranteed. If you need sorted output, use scandir() or sort the names yourself.

Practice

Practice
What is the function of readdir() in PHP?
What is the function of readdir() in PHP?
Was this page helpful?