Как сформировать список файлов в PHP: полное руководство с примерами
Способы получения массива файлов в PHP
Наиболее эффективное решение
Для быстрой выборки файлов по маске или расширению удобно использовать функцию glob(). Она возвращает массив путей, соответствующих шаблону, и поддерживает простые регулярные выражения.
$files = glob('/path/to/dir/*.txt');
print_r($files);
Пояснение:
- Шаблон
*.txtнаходит все файлы с расширением .txt в указанной директории. - Функция сама отсеивает каталоги, точки и точки-точки.
- Результат - индексированный массив строк.
Возможные проблемы:
Если в имени файла есть символы, которые интерпретируются как метасимволы (например, квадратные скобки), их надо экранировать. На Windows регистр букв игнорируется. Для пустого списка возвращается пустой массив.
Как получить все элементы директории без фильтрации по маске?
Используйте scandir(). Она возвращает массив всех записей, включая . и ...
$all = scandir('/path/to/dir');
print_r($all);
Для отсеивания служебных записей применяется array_diff():
$files = array_diff(scandir('/path/to/dir'), array('..', '.'));
Функция scandir не отфильтровывает каталоги, поэтому при необходимости оставить только файлы требуется дополнительная проверка с is_file(). Также не поддерживает маски, поэтому для выборки по расширению придётся применять array_filter().
Как использовать объектно-ориентированный подход для перебора файлов?
Класс DirectoryIterator предоставляет итератор по содержимому каталога.
$dir = new DirectoryIterator('/path/to/dir');
$files = [];
foreach ($dir as $item) {
if (!$item->isDot() && $item->isFile()) {
$files[] = $item->getFilename();
}
}
Методы isFile(), isDir(), getExtension() дают гибкий контроль.
При создании итератора с несуществующим путём возникает исключение RuntimeException. Требуется обработка через try..catch.
Как рекурсивно собрать все файлы из поддиректорий?
Класс RecursiveDirectoryIterator вместе с RecursiveIteratorIterator обходит древовидную структуру.
$rdi = new RecursiveDirectoryIterator('/path/to/dir');
$iter = new RecursiveIteratorIterator($rdi);
$files = [];
foreach ($iter as $spl) {
if ($spl->isFile()) {
$files[] = $spl->getPathname();
}
}
Можно также фильтровать по расширению, используя RecursiveCallbackFilterIterator.
Производительность рекурсивного обхода ниже, чем у glob с маской **/*.txt (доступна в PHP 5.3+). При большом количестве файлов возрастает время выполнения и потребление памяти.
Как отфильтровать в массиве только файлы (исключить каталоги) после scandir?
Комбинация array_filter() и is_file() с добавлением полного пути.
$base = '/path/to/dir';
$all = scandir($base);
$files = array_filter($all, function($name) use ($base) {
return is_file($base . DIRECTORY_SEPARATOR . $name);
});
$files = array_values($files); // сброс индексов
is_file() возвращает false для символических ссылок, если они ведут на несуществующий файл. Также при поломанных ссылках возможны false-negative.
Как получить файлы по сложной маске (несколько расширений)?
Шаблон glob с фигурными скобками (если включена опция GLOB_BRACE) позволяет задать несколько суффиксов.
$files = glob('/path/to/dir/{*.txt,*.md,*.log}', GLOB_BRACE);
Внимание: константа GLOB_BRACE не доступна на некоторых системах (например, на Solaris).
Альтернатива - собрать все файлы через glob('*') и отфильтровать по расширению через pathinfo().
Расширенные примеры работы с массивами файлов
Пример 1. Вывод всех файлов всех расширений с сортировкой по дате последнего изменения
$base = './docs';
$items = array_diff(scandir($base), ['.', '..']);
$files = array_filter($items, function($name) use ($base) {
return is_file($base . DIRECTORY_SEPARATOR . $name);
});
$withTime = [];
foreach ($files as $name) {
$path = $base . DIRECTORY_SEPARATOR . $name;
$withTime[$name] = filemtime($path);
}
arsort($withTime); // сортировка по убыванию даты
$result = array_keys($withTime);
print_r($result);
Результат - массив имён файлов, отсортированный от самых новых к старым.
Array
(
[0] => report_2025.html
[1] => notes.txt
[2] => archive.log
)
Пример 2. Рекурсивный сбор всех файлов с определённым расширением (без RecursiveIteratorIterator)
function getPhpFiles($dir) {
$result = [];
$items = scandir($dir);
foreach ($items as $item) {
if ($item === '.' || $item === '..') continue;
$full = $dir . DIRECTORY_SEPARATOR . $item;
if (is_dir($full)) {
$result = array_merge($result, getPhpFiles($full));
} elseif (pathinfo($full, PATHINFO_EXTENSION) === 'php') {
$result[] = $full;
}
}
return $result;
}
$phpFiles = getPhpFiles('/var/www');
print_r(array_slice($phpFiles, 0, 5));
Результат - первые 5 PHP-файлов из рекурсивного обхода.
Array
(
[0] => /var/www/index.php
[1] => /var/www/inc/config.php
[2] => /var/www/inc/db.php
[3] => /var/www/templates/header.php
[4] => /var/www/templates/footer.php
)
Проблема: рекурсия может переполнить стек при очень глубокой вложенности. Лучше использовать RecursiveDirectoryIterator.
Пример 3. Фильтрация файлов по размеру (от 1 КБ до 1 МБ)
$base = '/var/log';
$files = glob($base . '/*.log');
$filtered = array_filter($files, function($path) {
$size = filesize($path);
return $size > 1024 && $size < 1048576;
});
print_r($filtered);
В выдаче только файлы, размер которых лежит в указанном диапазоне.
Array
(
[0] => /var/log/access.log
[1] => /var/log/error.log
)
Функция filesize() кэширует результат; для актуальных данных используйте clearstatcache() перед вызовом. Большие объёмы файлов приводят к замедлению.
Пример 4. Использование glob с флагом GLOB_ONLYDIR
$dirs = glob('/path/*', GLOB_ONLYDIR);
print_r($dirs);
Возвращает только поддиректории. Полезно для обзора структуры.
Array
(
[0] => /path/templates
[1] => /path/public
[2] => /path/src
)
Пример 5. Комбинация array_map и pathinfo для извлечения имён без расширения
$files = glob('/img/*.{jpg,png,gif}', GLOB_BRACE);
$names = array_map(function($file) {
return pathinfo($file, PATHINFO_FILENAME);
}, $files);
print_r($names);
Результат: массив имён файлов, например ['photo1', 'photo2', 'logo'].
Array
(
[0] => photo1
[1] => photo2
[2] => logo
)
Пример 6. Обработка ошибок при открытии несуществующего каталога с помощью try..catch
try {
$dir = new DirectoryIterator('/invalid/path');
foreach ($dir as $item) {
// код
}
} catch (RuntimeException $e) {
echo 'Ошибка: ' . $e->getMessage();
}
Вывод сообщения об ошибке без прерывания скрипта.
Ошибка: DirectoryIterator::__construct(/invalid/path): Failed to open directory: No such file or directory