W3docs

scandir()

Подробное руководство по функции PHP scandir(): возвращаемые значения, сортировка, фильтрация и обработка ошибок.

Введение

Работа с директориями — неотъемлемая часть программирования на PHP: практически каждый скрипт резервного копирования, загрузчик файлов или обработчик ресурсов должен уметь просматривать содержимое папки. В этой статье мы подробно рассмотрим функцию PHP scandir(), которая читает содержимое директории за один вызов. Вы узнаете, что она возвращает, как сортировать и фильтровать результат, чем она отличается от glob(), и как безопасно обрабатывать ошибки.

Что такое scandir?

scandir() читает директорию и возвращает имена всех её элементов — файлов и поддиректорий — в виде плоского массива строк. Массив всегда включает два специальных элемента: . (текущая директория) и .. (родительская директория), поэтому их почти всегда нужно отфильтровать перед использованием результата.

Если директория не может быть прочитана, scandir() возвращает false и выдаёт предупреждение. Функция доступна начиная с PHP 4.3.0 и работает как на Unix-системах, так и на Windows.

Синтаксис

scandir(string $directory, int $sorting_order = SCANDIR_SORT_ASCENDING, ?resource $context = null): array|false
ПараметрОписание
$directoryПуть к директории, которую нужно прочитать. Может быть абсолютным или относительным рабочей директории скрипта.
$sorting_orderПорядок сортировки результата: SCANDIR_SORT_ASCENDING (по умолчанию, A→Z), SCANDIR_SORT_DESCENDING (Z→A) или SCANDIR_SORT_NONE (порядок файловой системы — самый быстрый, без сортировки).
$contextНеобязательный ресурс контекста потока (редко используется; нужен для пользовательских обёрток потоков).

Функция возвращает массив имён файлов в случае успеха или false в случае ошибки.

Имена возвращаются без пути к директории. Чтобы получить рабочий путь, добавьте директорию самостоятельно: $directory . '/' . $entry.

Как работает scandir?

В простейшем виде достаточно передать только путь к директории. Содержимое возвращается в алфавитном порядке (по возрастанию), поскольку это значение $sorting_order по умолчанию. Пример ниже фильтрует . и .. с помощью array_diff(), чтобы оставить только реальные элементы:

Пример использования функции scandir() в PHP

<?php

$dir = "/path/to/directory";
$files = scandir($dir);

// Filter out the current and parent directory entries
$filtered = array_diff($files, ['.', '..']);

foreach ($filtered as $file) {
    echo $file . "<br>";
}

Этот код выводит список файлов и поддиректорий в указанной директории, исключая . и ...

Сортировка содержимого директории

Передайте второй аргумент для управления порядком результата. Доступны три варианта:

  • SCANDIR_SORT_ASCENDING — алфавитный порядок A→Z (по умолчанию).
  • SCANDIR_SORT_DESCENDING — алфавитный порядок Z→A.
  • SCANDIR_SORT_NONE — без сортировки; элементы возвращаются в том порядке, который предоставляет файловая система. Это самый быстрый вариант, и его стоит использовать, если вы всё равно собираетесь сортировать список самостоятельно или когда порядок не важен.

Например, для директории, содержащей archive.txt, data.csv, report.txt, notes.md, image.png и поддиректорию backups:

Как отсортировать вывод scandir() в порядке убывания

<?php

$dir = "/path/to/directory";
$files = scandir($dir, SCANDIR_SORT_DESCENDING);

print_r($files);
// Array
// (
//     [0] => report.txt
//     [1] => notes.md
//     [2] => image.png
//     [3] => data.csv
//     [4] => backups
//     [5] => ..
//     [6] => .
// )

Те же данные с SCANDIR_SORT_NONE возвращаются без сортировки (точный порядок зависит от файловой системы), что позволяет избежать небольших накладных расходов на сортировку.

Получение только файлов (или только директорий)

scandir() возвращает файлы и папки вперемешку. Чтобы оставить только файлы, проверьте каждый элемент с помощью is_file(); чтобы оставить только директории — используйте is_dir(). Не забудьте сначала построить полный путь:

<?php

$dir = "/path/to/directory";
$entries = array_diff(scandir($dir), ['.', '..']);

$filesOnly = array_filter($entries, fn($entry) => is_file($dir . '/' . $entry));

print_r(array_values($filesOnly));
// Array
// (
//     [0] => archive.txt
//     [1] => data.csv
//     [2] => image.png
//     [3] => notes.md
//     [4] => report.txt
// )

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

Распространённая задача — получить только файлы определённого типа. Совместите scandir() с pathinfo() для чтения расширения каждого элемента:

<?php

$dir = "/path/to/directory";
$entries = array_diff(scandir($dir), ['.', '..']);

$textFiles = array_filter(
    $entries,
    fn($entry) => pathinfo($entry, PATHINFO_EXTENSION) === 'txt'
);

print_r(array_values($textFiles));
// Array
// (
//     [0] => archive.txt
//     [1] => report.txt
// )

Если вам нужно только совпадение файлов по шаблону, glob() справится с этим за один шаг — например, glob("$dir/*.txt") — и вернёт полные пути. Используйте glob() для поиска по шаблону и scandir(), когда нужны все элементы и полный контроль над фильтрацией.

Обработка ошибок

Функция scandir может завершиться с ошибкой, если указанный путь к директории недействителен или у директории нет соответствующих прав доступа. В случае ошибки она возвращает false и вызывает предупреждение. Исключения не выбрасываются, поэтому следует проверять возвращаемое значение напрямую. Пример:

Пример использования функции scandir() в PHP с обработкой ошибок

<?php

$dir = "/path/to/directory";
$files = scandir($dir);

if ($files === false) {
    echo "Error: Could not read the directory.";
} else {
    foreach ($files as $file) {
        echo $file . "<br>";
    }
}

Этот код проверяет возвращаемое значение scandir() и выводит сообщение об ошибке, если директория не может быть прочитана. Поскольку scandir() вызывает предупреждение (а не исключение) при ошибке, строгая проверка === false — это то, что реально защищает ваш код, а подавление предупреждения с помощью @scandir() не рекомендуется, так как вы теряете диагностическое сообщение.

Чтобы полностью избежать предупреждения, убедитесь, что путь является читаемой директорией перед вызовом scandir():

<?php

$dir = "/path/to/directory";

if (is_dir($dir)) {
    $files = scandir($dir);

    foreach (array_diff($files, ['.', '..']) as $file) {
        echo $file . "<br>";
    }
} else {
    echo "Error: '$dir' is not a valid directory.";
}

scandir() vs другие функции для работы с директориями

ФункцияВозвращаетЛучше всего для
scandir()Массив всех имён элементов сразуПолучение полного списка за один вызов с последующей фильтрацией/сортировкой
glob()Полные пути, соответствующие шаблонуПоиск по шаблону, например *.jpg
opendir() + readdir()Дескриптор директории, читаемый по одному элементуОчень большие директории, когда не нужно загружать весь список в память

Обзор более широкого набора инструментов см. в разделе Работа с директориями в PHP.

Заключение

Функция scandir() — это удобный способ прочитать содержимое директории в PHP за один вызов. Вы узнали, как перечислять элементы, сортировать их с помощью трёх констант SCANDIR_SORT_*, оставлять только файлы или только директории, фильтровать по расширению и безопасно обрабатывать ошибки. Используйте scandir(), когда нужен полный список и полный контроль; используйте glob(), когда достаточно простого поиска по шаблону.

Практика

Практика
Что делает функция scandir() в PHP?
Что делает функция scandir() в PHP?
Was this page helpful?