W3docs

readdir()

Функция PHP readdir() читает записи директории поочерёдно. Узнайте синтаксис, шаблоны цикла и сравнение с scandir() и glob().

Функция PHP readdir() читает по одной записи за раз из директории, которую вы уже открыли с помощью opendir(). Каждый вызов возвращает имя следующего файла или поддиректории и перемещает внутренний указатель вперёд, поэтому вызов функции в цикле позволяет обойти все элементы папки. На этой странице объясняется синтаксис, возвращаемое значение, шаблон цикла, помогающий избежать распространённой ошибки, и отличия readdir() от альтернатив более высокого уровня.

Синтаксис

readdir(resource $dir_handle = null): string|false
  • $dir_handle — дескриптор директории, возвращённый функцией opendir(). Если параметр не указан, PHP использует последний дескриптор, открытый opendir().
  • Возвращаемое значение — имя следующей записи в виде строки или false, когда записей больше нет. В результат включаются специальные имена . (текущая директория) и .. (родительская директория), а порядок следования записей соответствует порядку их хранения в файловой системе — без сортировки.

Чтение директории

Чтобы использовать readdir(), сначала откройте дескриптор директории с помощью opendir(), выполните цикл с readdir() до тех пор, пока функция не вернёт false, а затем освободите дескриптор с помощью 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);
}

Этот код открывает директорию, проходит по её содержимому и выводит все имена, кроме . и ... Вызов closedir() освобождает дескриптор по завершении работы.

Почему false !==, а не просто проверка на истинность

Строгое сравнение false !== ($entry = readdir($handle)) является обязательным, а не стилистическим. В директории вполне может быть файл с именем "0", и проверка на пустую строку также привела бы к сбоям. PHP считает строку "0" ложным значением, поэтому запись while ($entry = readdir($handle)) преждевременно прервала бы цикл при достижении такого файла. Строгое сравнение с false гарантирует, что цикл завершится только тогда, когда readdir() действительно исчерпает все записи.

Фильтрация записей по расширению

readdir() возвращает «сырые» имена, поэтому фильтрация целиком ложится на вас. Комбинируйте её с pathinfo(), чтобы оставлять только нужные типы файлов — например, изображения:

<?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) извлекает расширение из каждого имени, а in_array(..., true) (строгий режим) проверяет его по списку допустимых значений, выводя только совпадающие файлы.

Повторное чтение той же директории

Поскольку каждый вызов readdir() перемещает внутренний указатель вперёд, второй цикл по тому же дескриптору ничего не вернёт — указатель уже находится в конце. Используйте rewinddir(), чтобы сбросить его к первой записи без повторного открытия директории:

<?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() — это низкоуровневый строительный блок. В большинстве современного кода предпочтение отдаётся однострочным альтернативам:

  • scandir() возвращает все записи в виде отсортированного массива за один вызов — без необходимости управлять дескрипторами через opendir/closedir.
  • glob() сопоставляет шаблон в стиле оболочки (например, *.png) и возвращает полные пути, что делает фильтрацию по расширению однострочной операцией.

Выбирайте readdir(), когда нужно обрабатывать записи по одной, не загружая весь список в память (полезно для очень больших директорий), или когда требуется тонкий контроль над итерацией.

Распространённые ошибки

  • Всегда пропускайте . и ..readdir() включает их в результат, и забывчивость при фильтрации является самой частой ошибкой, особенно при рекурсивном обходе директорий.
  • opendir() может завершиться с ошибкой. Если путь не существует или недоступен для чтения, функция возвращает false и выдаёт предупреждение — именно поэтому в примерах цикл защищён условием if ($handle = opendir($dir)).
  • Закрывайте дескрипторы. Вызывайте closedir() (или дождитесь завершения скрипта), чтобы освободить ресурс.
  • Порядок не гарантирован. Если нужен отсортированный вывод, используйте scandir() или сортируйте имена самостоятельно.

Практика

Практика
Какова функция readdir() в PHP?
Какова функция readdir() в PHP?
Was this page helpful?