Php перебрать все файлы в папке. Scandir - Получает список файлов и каталогов, расположенных по указанному пути

В данном уроке мы разберемся с типовой задачей, которая возникает во время работы над проектом PHP: получение списка файлов и директорий. Обсудим несколько базовых и более изощренных подходов, с перечисление плюсов и минусов каждого. Первые три решения будут использовать типовые функции PHP, а затем представим более надежное с применением итераторов SPL.

Для предметного обсуждения решения и демонстраций предположим, что структура директорий имеет следующий вид:

\---manager | \---user | \---document.txt | \---data.dat | \---style.css |---article.txt |---master.dat |---script.php |---test.dat |---text.txt

Базовые решения

Первый набор решений основан на использовании функции glob() , комбинации функций opendir() , readdir() и closedir() , и также функции scandir() .

Использование glob()

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

  • $pattern (обязательный): шаблон поиска
  • $flags (опциональный): один или несколько флагов, описание которых можно найти в документации

Рассмотрим примеры. Для поиска в директории всех файлов и директорий, имена которых заканчиваются на .txt , следует использовать код:

Если вывести переменную $filelist , то получим:

Array (0 => "article.txt", 1 => "text.txt")

Если нужен список файлов и директорий, имена которых начинаются на “te”, то код будет выглядеть так:

А вывод имеет вид:

Array (0 => "test.dat", 1 => "text.txt")

А для получения списка только директорий с именами, содержащих “ma”, используем код:

Последний пример выведет:

Array (0 => "manager")

Обратите внимание, что в последнем примере использован флаг GLOB_ONLYDIR в качестве второго параметра функции. Поэтому файл master.dat исключен из списка. Хотя функция glob() очень проста в использовании, иногда она недостаточно гибкая. Например, нет флага для получения только файлов (без директорий), которые соответствуют шаблону.

Используем opendir() , readdir() , и closedir() .

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

Функция opendir() открывает директорию и возвращает дескриптор соединения. Как только дескриптор получен, можно использовать функцию readdir() . С каждым обращением данная функция выдает имя следующего файла или директории внутри открытого каталога. Если все имена уже были перечислены, функция возвращает false . Для закрытия дескриптора используется функция closedir() .

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

Ниже приведенный пример возвращает список имен файлов и директорий начинающихся на “te”:

При выполнении выше приведенного кода, переменная $entry будет содержать такие включения, как “.” и “..”. Это две виртуальные директории, которые имеются в каждом каталоге файловой системы. Они представляют текущий каталог и родительский каталог соответственно.

Второй пример выводит только файлы, содержащиеся в заданном каталоге.

Пример выдаст следующее:

Array (0 => "article.txt", 1 => "master.dat", 2 => "script.php", 3 => "test.dat", 4 => "text.txt")

Использование scandir()

В завершение представим функцию scandir() . Она имеет только один обязательный параметр: путь для чтения. Функция возвращает массив файлов и директорий, расположенных по указанному пути. Для получения списка файлов и директорий по определенному критерию нужно выполнить дополнительную фильтрацию. С другой стороны, решение получается более кратким и не требует управления дескрипторами.

Данный пример показывает, как получить список файлов и каталогов, имена которых начинаются на “te”:

Воспользуемся итераторами SPL

Теперь рассмотрим использование итераторов SPL . Но прежде, чем приступить к решению нашей задачи, проведем введение в библиотеку SPL и итераторы. Библиотека SPL предоставляет серию классов для объектно ориентированных структур данных, итераторов, дескрипторов файлов и прочее.

Одно из преимуществ итераторов заключается в том, что они являются классами и их можно расширить для удовлетворения собственных нужд. Другой плюс состоит в том, что итераторы имеют собственные методы, которые являются полезными при решении множества типовых задач и располагаются в одном месте. Посмотрите на пример использования FilesystemIterator в сравнении с readdir() . Оба метода применяют цикл, но в случае readdir() вы обрабатываете только строку, а FilesystemIterator работает с объектом, который может содержать дополнительную информацию о файле или директории (размер, владелец, права доступа и так далее).

Конечно, PHP представляет возможность для получения такой информации с помощью функций,например filesize() и fileowner(). Но PHP5 основан на использовании концепции ООП. Поэтому лучше использовать современные методы работы с языком программирования. На нашем сайте есть уроки, посвященные работе с итераторами .

Как уже сообщалось во водной части урока, мы рассмотрим использование FilesystemIterator , RecursiveDirectoryIterator и GlobIterator . Первый наследуется от DirectoryIterator , а остальные от FilesystemIterator . Они все имеют один и тот же конструктор, который принимает два параметра:

  • $path (обязательный): путь к пункту файловой системы, над которым совершаются операции
  • $flags (опциональный): один или несколько флагов, перечисленных в документации

Реальное различие в данных итераторах заключается в их использовании для навигации по заданному пути.

FilesystemIterator

Использовать FilesystemIterator очень просто. Рассмотрим в действии. Представляем два примера. Первый показывает поиск всех файлов и каталогов, имена которых начинаются на “te”. Второй пример использует другой итератор RegexIterator для поиска всех файлов и каталогов, имена которых заканчиваются на “t.dat” или “t.php”. Итератор RegexIterator используется для фильтрации результата на основе регулярных выражений.

getFilename(), "te") === 0) { $filelist = $entry->getFilename(); } }

Выше приведенный код выдаст результат, аналогичный предыдущим примерам.

Второй пример с применением RegexIterator:

getFilename(); }

Он будет выводить:

Array (0 => "script.php", 1 => "test.dat")

RecursiveDirectoryIterator

Итератор RecursiveDirectoryIterator обеспечивает интерфейс для рекурсивного прохода по директориям файловой системы. Он имеет несколько полезных методов, таких как getChildren() и hasChildren() , которые возвращают итератор для текущего места, если это директория, и проверяют, является ли текущая точка входа директорией. Следующий пример демонстрирует использование RecursiveDirectoryIterator и getChildren() . Результат будет такой же, как и в предыдущих примерах.

getChildren(), "/t\.(php|dat)$/"); $filelist = array(); foreach($filter as $entry) { $filelist = $entry->getFilename(); }

GlobIterator

Итератор GlobIterator выполняет проход по файловой системе также, как и функция glob() . Первый параметр может включать шаблон для имени. Пример демонстрирует использование GlobIterator с тем же результатом, что и ранее.

getFilename(); }

Заключение

В данном уроке демонстрируется использование различных подходов для достижение одинаковой цели: получение списка файлов и директорий. Следует запомнить следующие ключевые моменты:

  • Функция glob() является встроенным решением, но она недостаточно гибкая.
  • Решение на основе opendir() , readdir() , и closedir() более сложное и требует дополнительной фильтрации, но оно более гибкое.
  • Функция scandir() требует дополнительной фильтрации, но работает без обработки дескриптора.
  • Если вы используете подход ООП, то следует применять библиотеку SPL. Дополнительно вы можете расширить классы своим функционалом.
  • Итератор GlobIterator имеет функцию предварительной фильтрации, а другие используют RegexIterator .

Работа с файлами

Необходимость в операциях с файлами встает перед программистом очень часто. Если ваши скрипты не используют баз данных, то файлы остаются единственными приемлемыми хранителями информации для скрипта. Применение файлов как хранилищ информации выполнения скрипта позволяет использовать их в самых разнообразных ситуациях. Практически все скрипты-счетчики чего-либо написаны на основании работы с файлами. Также возможно привести кучу других примеров, но пора переходить непосредственно от слов к делу.

Сразу хочу сказать, что работа с файлом должна быть санкционирована. По умолчанию PHP не допускает работу с файлом в целях безопасности. Чтобы снять этот запрет в FTP-менеджере CuteFTP в свойствах файла выставьте все галочки, в других менеджерах должно быть что-то подобное.

file_exists

Прежде, чем производить операции с файлом, часто необходимо убедиться, что указанный файл вообще существует. Этим и занимается функция file_exists . Эта функция может возвращать только два значения, как вы сами понимаете, TRUE (если указанный файл существует) и FALSE . Обычно использование данной функции выглядит так:

Заметьте, что функция действует только на локальных файлах, то есть если вы возжелаете проверить, обзавелся ли Яндекс файлом robot.txt, то ваши усилия будут тщетны. Но зато возможно проверить любой файл, лежащий на локальном сервере независимо от директории его расположения.

Вот некоторые правила описания пути к файлу.

filesize

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

file

Эта функция уже непосредственно работает с файлом. Она возвращает содержимое указанного файла, причем делает она это в виде массива, где каждый его элемент является строкой файла. Функция полезна, когда в одном файле необходимо сохранить несколько разных значений, которые не должны пересекаться. Тогда каждое значение сохраняется на отдельной строке и читается функцией file , которая возвращает массив, вследствие чего обращение к заданной переменной происходит с помощью чтения значения элемента массива с индексом, соответствующим строке в файле.

Кроме того, возможно воссоединение всех элементов возвращенного массива в одну переменную. Это делается с помощью функции работы с массивами implode .

fopen

Если предыдущая функция самодостаточна и в общем не связана с другими функциями, то последующие функции работы с файлами работают в связке с fopen . Эта функция открывает указанный файл и возвращает идентификатор соединения с файлом, который используется в служебных целях. С содержимым файла эта функция никаким образом не связывается.

Функция fopen имеет несколько режимов работы с файлом. Они указываются после имени файла и представляют из себя следующие обозначения:

    "r"
    Файл открывается только для чтения его содержимого.

    "r+"
    Открытие файла как для чтения, так и для записи.

    "w"
    Файл открывается с целью записи.

    "w+"
    Открыть файл для чтения и записи.

    "a"
    Файл открывается для записи в конец файла (дозаписи).

    "a+"
    Открывается для дозаписи и чтения.

fgets

Функция чтения файла, открытого функцией fopen . Но в отличие от file , эта функция за каждый раз своего выполнения возвращает только одну строку файла, при этом она перемещает внутренний указатель файла на следующую строку, которую она прочитает при следующем обращении к функции. Поэтому, если вам необходимо прочитать файл целиком, необходимо использовать эту функцию в цикле.

Заметьте, что функция fgets использует дополнительный параметр length , который указывает максимальную длину строки файла для чтения. Если объем строки превышает это число, то функция возратит ее в "урезанном" виде объемом в число length байт. По умолчанию этот параметр установлен в 1024 байт, или в один килобайт. Тем более обратите внимание на этот параметр, если вы используете файлы больших размеров, так как при чтении таких файлов может переполниться буфер выполнения PHP (его объем указывается в файле конфигурации), что приведет к зависанию.

Обратите внимание, что в качестве указания файла для чтения необходимо указывать не имя файла, а идентификатор соединения с файлом, возвращенный функцией fopen (в нашем примере это значение переменной $file).

fputs

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

fclose

Как вы догадались, эта функция закрывает указанный файл. Вообще-то, по завершении выполнения скрипта, PHP сам закрывает все открытые им файлы, но все же лучше это делать вручную. В качестве параметра функции необходимо указать идентификатор соединения с файлом.

Для иллюстрации связки вышеуказанных функций приведем пример создания простого счетчика посещений.

$file = fopen("counter.txt", "r");
$c = fgets ($file, 150);
fclose ($file);
$c++;
$file = fopen("counter.txt", "w");
fputs ($file, $c);
fclose ($file);
echo $c;
?>

Работа с директориями

Тесно связаны с действиями над файлами операции с директориями. Алгоритм работы с ними схож с операциями над файлами: сначала директорию необходимо открыть, выполнить какие-либо действия и, наконец, закрыть ее.

opendir

Эта функция открывает указанную директорию и возвращает служебный идентификатор соединения с директорией. Пути к директории следует указывать следующим образом:

Точка означает открытие текущей директории

. /files/

Открытие папки files , находящейся в текущей директории

Открытие папки на уровень выше текущей

readdir

Функция читает директорию, открытую opendir . За каждый проход она возвращает имя файла или папки, лежащих в указанной директории, и перемещает внутренний указатель на следующий объект директории. Так что для прочтения всей директории ее необходимо использовать в цикле.

Также необходимо заметить, что эта функция возвращает служебные объекты папки . и .. , которые можно отсекать при выводе оператором IF .

closedir

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

Иногда использование функций работы с директориями очень облегчают жизнь. Например, в разделе Функции вы можете видеть список функций в алфавитном порядке. Представляете, сколько времени нужно было бы потратить, чтобы вручную написать весь этот список с ссылками, да еще и в алфавитном порядке. И вот как раз здесь мне помогли функции работы с директорией. Каждая функция была помещена в отдельный файл с именем, соответствующим названию функции, без каких-либо расширений.

Так что, при каждом заходе на страницу вы получаете только что сгенерированный список функций.

На этом все. Встретимся на следующем уроке.

scandir — Получает список файлов и каталогов, расположенных по указанному пути

Описание

Array scandir (string $directory [, int $sorting_order = SCANDIR_SORT_ASCENDING [, resource $context ]])

Возвращает array , содержащий имена файлов и каталогов, расположенных по пути, переданном в параметре directory .

Список параметров

Сканируемый каталог.

Sorting_order

По умолчанию, сортировка производится в алфавитном порядке по возрастанию. Если необязательный параметр sorting_order установлен в значение SCANDIR_SORT_DESCENDING , сортировка производится в алфавитном порядке по убыванию. Если же он установлен в значение SCANDIR_SORT_NONE , то сортировка не производится.

Context

За описанием параметра context обратитесь к разделу "Потоки " данного руководства.

Возвращаемые значения

Возвращает array имен файлов в случае успеха или FALSE в случае ошибки. Если directory не является каталогом, возвращается FALSE и генерируется сообщение об ошибке уровня E_WARNING .

Список изменений

Примеры

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

$dir = "/tmp" ;
$files1 = scandir ($dir );
$files2 = scandir ($dir , 1 );

Print_r ($files1 );
print_r ($files2 );
?>

Результатом выполнения данного примера будет что-то подобное:

Array ( => . => .. => bar.php => foo.txt => somedir) Array ( => somedir => foo.txt => bar.php => .. => .)

Пример #2 Альтернативный вариант функции scandir() для PHP 4

$dir = "/tmp" ;
$dh = opendir ($dir );
while (false !== ($filename = readdir ($dh ))) {
$files = $filename ;
}

Sort ($files );

Print_r ($files );

Rsort ($files );

Print_r ($files );

Листинг директорий - это получение информации о каталогах и файлах для заданной родительской директории, а также возможность применить к этим данным различные фильтры для коррекции вывода.

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


Для более наглядного представления используем структуру директорий, которая имеет следующий вид:


\-Application | \-User | \-data.apk | \-style.css | \-test.txt |-readme.txt |-script.php |-serial.txt |-test.html |-test.js

Базовые решения
Первый набор примеров использует функции glob() и комбинации функций opendir() , readdir() , closedir() , а также функцию scandir() .

Использование glob()

Пример использования php функции glob() , которая позволяет выполнять поиск пути по шаблону.
Функция glob($pattern ,$flags ) оперирует двумя аргументами:
  • $pattern (обязательный): строка шаблона поиска
  • $flags
    • GLOB_MARK - Добавляет слеш к каждой возвращаемой директории.
    • GLOB_NOSORT - Возвращает файлы в том виде, в котором они содержатся в директории (без сортировки). Если этот флаг не указан, то имена сортируются по алфавиту.
    • GLOB_NOCHECK - Возвращает шаблон поиска, если с его помощью не был найден ни один файл.
    • GLOB_NOESCAPE - Обратные слеши не экранируют мета символы.
    • GLOB_BRACE - Раскрывает {a,b,c} для совпадения с "a", "b" или "c".
    • GLOB_ONLYDIR - Возвращает только директории, совпадающие с шаблоном.
    • GLOB_ERR - Останавливается при ошибках чтения (например, директории без права чтения), по умолчанию ошибки игнорируются.
Для поиска в директории всех файлов и директорий, имена которых заканчиваются на.txt, следует используется код: В выводе получим такой результат: array(2) { => string(10) "readme.txt" => string(10) "serial.txt" } Если необходимо получить список файлов и директорий, имена которых начинаются на "te": В выводе получим такой результат: array(2) { => string(9) "test.html" => string(7) "test.js" } Получение в списке только директорий с именами, содержащими "er": В выводе получим такой результат: array(1) { => string(4) "User" }

В последнем примере использован флаг GLOB_ONLYDIR в качестве второго аргумента функции. Поэтому в список попала, только директория "User" в имени, которой встречается "er". Функция glob() очень проста в использовании, но иногда она недостаточно гибкая. Нет флага для получения только файлов (без директорий), которые соответствуют шаблону.

Использование opendir(), readdir(), и closedir().

Следующий метод получения списка файлов и директорий, заключается в использовании PHP функций opendir() , readdir() и closedir() .

Функция opendir() возвращает дескриптор открытой директории. После того как дескриптор получен, можно использовать функцию readdir() . При обращении к дескриптору функция readdir() выдает имя следующего файла или директории. Если все элементы содержащиеся в дескрипторе уже были перечислены, функция readdir() вернет false . Для закрытия дескриптора используем функцию closedir() .


В отличие от использования php функции , данный подход немного сложнее. Отсутствует возможность задать параметры фильтрации, которые помогают заранее формировать список возвращаемых имен файлов и директорий. Для получения необходимого списка файлов и директорий, фильтрацию должна быть выполнена самостоятельно.


Приведенный пример возвращает список имен файлов и директорий начинающихся на "Us": В выводе получим такой результат: array(1) { => string(4) "User" } Следующий пример выведет только файлы, содержащиеся в заданном каталоге. В выводе получим такой результат: array(5) { => string(10) "script.php" => string(7) "test.js" => string(9) "test.html" => string(10) "serial.txt" => string(10) "readme.txt" }

Использование scandir().

Для завершения посмотрим пример использования php функции scandir() . У нее есть только один обязательный атрибут - путь к директории для чтения. Результатом работы функции является массив файлов и директорий, расположенных по заданному в аргументе пути. Как и в предыдущем примере для получения отфильтрованного списка файлов и директорий необходимо выполнить ее самостоятельно. Визуально решение получается более коротким и не требуется управление дескрипторами.


Пример показывает, как получить список файлов и каталогов, имена которых начинаются на "te": В выводе получим такой результат: array(2) { => string(9) "test.html" => string(7) "test.js" }

Продвинутое решение c использованием PHP SPL
Более надежное решение с применением SPL итераторов FilesystemIterator , RecursiveDirectoryIterator и GlobIterator .

Использование итераторов SPL.

Рассмотрим использование итераторов SPL. До того как приступить к решению задачи, немного познакомимся с php библиотекой SPL и итераторами. SPL библиотека предоставляет из себя специализированные наборы классов для объектно ориентированных структур данных, итераторов, дескрипторов файлов и прочее.


Основное преимущество итераторов заключается в том, что они являются классами и их можно расширить используя стандартный механизм php наследования классов. Еще один плюс заключается в том, что итераторы имеют собственные методы, которые могут быть полезны при решении типовых задач и все они расположены в одном месте. Посмотрим на примере использования FilesystemIterator и сравним с readdir() . Оба метода используют цикл, но в случае readdir() получится обрабатывать только строку, а FilesystemIterator может работать с объектом. В котором может содержатся дополнительная информацию о файле или директории такие как владелец, размер, права доступа и так далее.


Разумеется у PHP есть возможности для получения этой информации с помощью функций, filesize() , fileowner() и других. Но PHP как и любой язык программирования имеет свойства меняться. В PHP5 все больше прослеживается стремление задействовать концепции ООП. Поэтому лучше использовать современные методы работы с языком программирования.


Рассмотрим использование FilesystemIterator , RecursiveDirectoryIterator и GlobIterator . Первый итератор наследуется от DirectoryIterator , а остальные от FilesystemIterator . Все они имеют один и тот же конструктор, который принимает два аргумента:

  • $path (обязательный): путь к пункту файловой системы, над которым совершаются операции
  • $flags (не обязательный): один или несколько флагов
    • FilesystemIterator::CURRENT_AS_PATHNAME Заставляет метод FilesystemIterator::current() вернуть путь.
    • FilesystemIterator::CURRENT_AS_FILEINFO Заставляет метод FilesystemIterator::current() вернуть экземпляр SplFileInfo.
    • FilesystemIterator::CURRENT_AS_SELF Заставляет метод FilesystemIterator::current() вернуть $this (FilesystemIterator).
    • FilesystemIterator::CURRENT_MODE_MASK Маскирует FilesystemIterator::current()
    • FilesystemIterator::KEY_AS_PATHNAME Заставляет метод FilesystemIterator::key() вернуть путь.
    • FilesystemIterator::KEY_AS_FILENAME Заставляет метод FilesystemIterator::key() вернуть имя файла.
    • FilesystemIterator::FOLLOW_SYMLINKS Заставляет метод RecursiveDirectoryIterator::hasChildren() следовать символическим ссылкам.
    • FilesystemIterator::KEY_MODE_MASK Маскирует FilesystemIterator::key()
    • FilesystemIterator::NEW_CURRENT_AND_KEY Тоже, что FilesystemIterator::KEY_AS_FILENAME | FilesystemIterator::CURRENT_AS_FILEINFO.
    • FilesystemIterator::SKIP_DOTS Пропускает точечные файлы (. and ..).
    • FilesystemIterator::UNIX_PATHS Заставляет все пути использовать обратный слеш в Unix-стиле, независимо от настроек системы по умолчанию.

Различие в данных итераторах заключается в их использовании для навигации по заданному пути.

FilesystemIterator

Использовать FilesystemIterator очень просто.
Пример показывает поиск всех файлов и каталогов, имена которых начинаются на "te".

getFilename(),"te")===0): $arFileList = $obFile->getFilename(); endif; endforeach; //Выводим результат var_dump($arFileList); ?> В выводе получим такой результат: array(2) { => string(7) "test.js" => string(9) "test.html" }

Пример использования другого итератора RegexIterator для поиска всех файлов и каталогов, имена которых заканчиваются на "t.js" или "t.php". Итератор RegexIterator используется для фильтрации результата и использует механизм регулярных выражений.

getFilename(); endforeach; //Выводим результат var_dump($arFileList); ?> В выводе получим такой результат: array(2) { => string(10) "script.php" => string(7) "test.js" }

RecursiveDirectoryIterator

Итератор RecursiveDirectoryIterator обеспечивает интерфейс для рекурсивного прохода по директориям файловой системы. Он имеет несколько полезных методов, таких как getChildren() и hasChildren() , которые возвращают итератор для текущего места, если это директория, и проверяют, является ли текущая точка входа директорией.


RecursiveDirectoryIterator и getChildren() . getChildren(), "/t\.(txt|css)$/"); $arFileList = array(); foreach($rxIterator as $obFile): $arFileList = $obFile->getFilename(); endforeach; //Выводим результат var_dump($arFileList); ?> В выводе получим такой результат в данном случае - это файл из директории "User": array(1) { => string(8) "test.txt" }

GlobIterator

Итератор GlobIterator выполняет проход по файловой аналогично функции . Первый атрибут может включать шаблон имени.


Пример демонстрирует использование GlobIterator с тем же результатом, что и ранее. getFilename(); endforeach; //Выводим результат var_dump($arFileList); ?> В выводе получим такой результат: array(2) { => string(10) "/test.html" => string(8) "/test.js" }

Заключение

В приведенных выше примерах были рассмотрены различные методы PHP для достижения одной и той же цели: получение списка файлов и директорий.

Из примеров можно выделить следующие основные моменты:
Похожие публикации