Для поиска файлов на сервере хорошо подходит функция glob(), которая возвращает список файлов по заданной маске, например:
$files = glob('/tmp/*.jpg');
PHP
В маске можно использовать следующие специальные символы:
* |
Соответствует нулю или большему количеству любых символов. |
? |
Один любой символ. |
[...] |
Один символ входящий в группу. |
[!...] |
Один символ не входящий в группу. |
{...,...} |
Вхождение подстрок, работает с флагом GLOB_BRACE . |
|
Экранирует следующий символ, кроме случаев, когда используется флаг GLOB_NOESCAPE . |
Доступные флаги:
GLOB_MARK |
Добавляет слеш к каждой возвращаемой директории. |
GLOB_NOSORT |
Возвращает файлы в том виде, в котором они содержатся в директории (без сортировки). Если этот флаг не указан, то имена сортируются по алфавиту. |
GLOB_NOCHECK |
Возвращает шаблон поиска, если с его помощью не был найден ни один файл. |
GLOB_NOESCAPE |
Обратные слеши не экранируют метасимволы. |
GLOB_BRACE |
Раскрывает {a,b,c} для совпадения с «a », «b » или «c ». |
GLOB_ONLYDIR |
Возвращает только директории, совпадающие с шаблоном. |
GLOB_ERR |
Останавливается при ошибках чтения (например, директории без права чтения), по умолчанию ошибки игнорируются. |
Возможно использовать несколько флагов:
$files = glob('/tmp/*.jpg', GLOB_NOSORT|GLOB_ERR);
PHP
Далее во всех примерах используется папка tmp со следующим содержимым:
1
Поиск в директории
Список всех файлов и директорий
$dir = __DIR__ . '/tmp';
$files = array();
foreach(glob($dir . '/*') as $file) {
$files[] = basename($file);
}
print_r($files);
PHP
Результат:
Array
(
[0] => 1.svg
[1] => 2.jpg
[2] => 22-f.gif
[3] => 22.svg
[4] => img.png
[5] => path
[6] => prod.png
[7] => style-1.txt
[8] => style-2.css
)
Только файлы
$dir = __DIR__ . '/tmp';
$files = array();
foreach(glob($dir . '/*') as $file) {
if (is_file($file)) {
$files[] = basename($file);
}
}
print_r($files);
PHP
Результат:
Array
(
[0] => 1.svg
[1] => 2.jpg
[2] => 22-f.gif
[3] => 22.svg
[4] => img.png
[5] => prod.png
[6] => style-1.txt
[7] => style-2.css
)
Только директории
$dir = __DIR__ . '/tmp';
$files = array();
foreach(glob($dir . '/*') as $file) {
if (is_dir($file)) {
$files[] = basename($file);
}
}
print_r($files);
PHP
Результат:
Array
(
[0] => path
)
Поиск по расширению
$dir = __DIR__ . '/tmp';
$files = array();
foreach(glob($dir . '/*.svg') as $file) {
$files[] = basename($file);
}
print_r($files);
PHP
Результат:
Array
(
[0] => 1.svg
[1] => 22.svg
)
Поиск по нескольким расширениям
$dir = __DIR__ . '/tmp';
$files = array();
foreach(glob($dir . '/*.{jpg,png}', GLOB_BRACE) as $file) {
$files[] = basename($file);
}
print_r($files);
PHP
Результат:
Array
(
[0] => 2.jpg
[1] => img.png
[2] => prod.png
)
Поиск по имени файла
Например, в названия файлов начинаются со слова «style»:
$dir = __DIR__ . '/tmp';
$files = array();
foreach(glob($dir . '/style*.*') as $file) {
$files[] = basename($file);
}
print_r($files);
PHP
Результат:
Array
(
[0] => style-1.txt
[1] => style-2.css
)
Или начинаются с цифр:
$dir = __DIR__ . '/tmp';
$files = array();
foreach(glob($dir . '/[0-9]*.*', GLOB_BRACE) as $obj) {
$files[] = basename($obj);
}
print_r($files);
PHP
Результат:
Array
(
[0] => 1.svg
[1] => 2.jpg
[2] => 22-f.gif
[3] => 22.svg
)
2
Поиск в дереве
Поиск по всем подкатегориям более сложный т.к. требует применение рекурсии.
Список всех файлов
function glob_tree_files($path, $_base_path = null)
{
if (is_null($_base_path)) {
$_base_path = '';
} else {
$_base_path .= basename($path) . '/';
}
$out = array();
foreach(glob($path . '/*') as $file) {
if (is_dir($file)) {
$out = array_merge($out, glob_tree_files($file, $_base_path));
} else {
$out[] = $_base_path . basename($file);
}
}
return $out;
}
$dir = __DIR__ . '/tmp';
$files = glob_tree_files($dir);
print_r($files);
PHP
Результат:
Array
(
[0] => 1.svg
[1] => 2.jpg
[2] => 22-f.gif
[3] => 22.svg
[4] => img.png
[5] => path/icon-rew.png
[6] => path/marker.png
[7] => path/psd/1.psd
[8] => path/psd/2.psd
[9] => path/psd/index.psd
[10] => path/sh-1.png
[11] => path/title-1.png
[12] => prod.png
[13] => style-1.txt
[14] => style-2.css
)
Список всех директорий
function glob_tree_dirs($path, $_base_path = null)
{
if (is_null($_base_path)) {
$_base_path = '';
} else {
$_base_path .= basename($path) . '/';
}
$out = array();
foreach(glob($path . '/*', GLOB_ONLYDIR) as $file) {
if (is_dir($file)) {
$out[] = $_base_path . basename($file);
$out = array_merge($out, glob_tree_dirs($file, $_base_path));
}
}
return $out;
}
$dir = __DIR__ . '/tmp';
$files = glob_tree_dirs($dir);
print_r($files);
PHP
Результат:
Array
(
[0] => path
[1] => path/psd
)
Поиск по имени/расширению
function glob_tree_search($path, $pattern, $_base_path = null)
{
if (is_null($_base_path)) {
$_base_path = '';
} else {
$_base_path .= basename($path) . '/';
}
$out = array();
foreach(glob($path . '/' . $pattern, GLOB_BRACE) as $file) {
$out[] = $_base_path . basename($file);
}
foreach(glob($path . '/*', GLOB_ONLYDIR) as $file) {
$out = array_merge($out, glob_tree_search($file, $pattern, $_base_path));
}
return $out;
}
$path = __DIR__ . '/tmp';
$files = glob_tree_search($path, '*.{jpg,png}');
print_r($files);
PHP
Результат:
Array
(
[0] => 2.jpg
[1] => img.png
[2] => prod.png
[3] => path/icon-rew.png
[4] => path/marker.png
[5] => path/sh-1.png
[6] => path/title-1.png
)
Чтобы в результирующих списках выводились полные пути к файлам, достаточно удалить функцию basename()
.
Другие публикации
Можно найти множество применений Яндекс Диска на своем сайте, например, хранение бекапов и отчетов, обновление прайсов,…
Протокол FTP – предназначен для передачи файлов на удаленный хост. В PHP функции для работы с FTP как правило всегда доступны и не требуется установка дополнительного расширения.
В статье приведен пример формы и php-скрипта для безопасной загрузки файлов на сервер, возможные ошибки и рекомендации при работе с данной темой.
phpQuery – это удобный HTML парсер взявший за основу селекторы, фильтры и методы jQuery, которые позволяют…
Один из вариантов поиска похожих статей в базе данных основан на схождении слов в двух текстах.
Ниже приведён список MIME-заголовков и расширений файлов.
Привет, друзья! Довелось мне поработать на одном коммерческом сайте. И, как выяснилось, с течением недолгого времени на сайте пропала часть изображений. Удалять их, конечно же, никто не удалял, и предположения были, что папку случайно перенесли в другое место.
Да, бывает и такое. Но суть сейчас не в этом. А в том, как я искал эту папку. Поскольку мне были известны имена некоторых файлов (а это уже хорошая зацепка при поиске), то я решил написать небольшой скрипт для поиска этих файлов по всему сайту. Вдобавок ко всему специально для аудитории сайта я доработал поиск и сделал несколько разных его вариантов.
Два варианта поиска файлов по названию на PHP
В этом блоке я представляю вашему вниманию два разных варианта поиска файлов на вашем хостинге по названию.
1. Точный поиск по названию:
<?php
header("Content-Type: text/html; charset=utf-8");
$path = $_SERVER["DOCUMENT_ROOT"];
$directory = new RecursiveDirectoryIterator($path);
$iterator = new RecursiveIteratorIterator($directory);
foreach ($iterator as $info) {
$name_file = substr($info->getfileName(), 0, strrpos($info->getfileName(), "."));
$name_search = array("robots", "www_pandoge_com"); // Список файлов
foreach($name_search as $key_name) {
if($name_file == $key_name) {
echo $info->getPathname()."<br>";
}
}
}
?>
2. Неточный поиск (по наличию слова в названии):
<?php
header("Content-Type: text/html; charset=utf-8");
$path = $_SERVER["DOCUMENT_ROOT"];
$directory = new RecursiveDirectoryIterator($path);
$iterator = new RecursiveIteratorIterator($directory);
foreach ($iterator as $info) {
$name_file = substr($info->getfileName(), 0, strrpos($info->getfileName(), "."));
$name_search = array("robots", "www_pandoge_com"); // Список файлов
foreach($name_search as $key_name) {
if(preg_match("/".$key_name."/", $name_file)) {
echo $info->getPathname()."<br>";
}
}
}
?>
Во всех вариантах – переменная $name_search содержит в себе слово (слова) для вашего поиска по файлам.
Код вы вставляете в файл PHP с любым именем, после чего грузите его на ваш хостинг.
Обращаетесь к нему на вашем сайте, и на выходе (при положительном результате) вы получите список найденных файлов с полным их местоположением.
Поиск файлов по расширению на PHP
В поисках файлов по расширению, как вы поняли, не учитывается имя, а учитывается его формат. Например, у изображений это может быть PNG, JPG или GIF, а у аудиофайлов – MP3, WAVE и другие.
Код для поиска:
<?php
header("Content-Type: text/html; charset=utf-8");
$path = $_SERVER["DOCUMENT_ROOT"];
$directory = new RecursiveDirectoryIterator($path);
$iterator = new RecursiveIteratorIterator($directory);
foreach ($iterator as $info) {
$file_formal = substr($info->getfileName(), strrpos($info->getfileName(), ".") + 1);
$name_search = array("mp3", "jpg"); // Список форматов
foreach($name_search as $key_name) {
if($file_formal == $key_name) {
echo $info->getPathname()."<br>";
}
}
}
?>
Его вы также вставляете в PHP-файл, грузите на хостинг и обращаетесь для получения результатов поиска.
Обратите внимание, что регистр во всех вариантах имеет значение. И, например, если файл на хостинге имеет расширение MP3, а в переменной для поиска вы указали «mp3» – файлы найдены не будут. Но этот момент можно подправить с помощью функции «mb_strtolower».
Please note that I want the compartment number to change.
<?php
$compartment = "1";
/* HERE I NEED SOME SCRIPT TO FIND THE EXTENSION OF THE FILE NAME $compartment AND TO SAVE THAT AS A VARIABLE NAMED 'EXTENSION'.*/
if (file_exists($compartment.$extension)) {
echo "$compartment.$extension exists!
} else {
echo "No file name exists that is called $compartment. Regardless of extension."
}
?>
<?php
$compartment = "2";
/* HERE I NEED SOME SCRIPT TO FIND THE EXTENSION OF THE FILE NAME $compartment AND TO SAVE THAT AS A VARIABLE NAMED 'EXTENSION'.*/
if (file_exists($$compartment.$extension)) {
echo "$compartment.$extension exists!
} else {
echo "No file name exists that is called $compartment. Regardless of extension."
}
?>
Thank You!
asked Jul 8, 2010 at 9:26
Andy CheesemanAndy Cheeseman
2831 gold badge3 silver badges13 bronze badges
3
You need glob()
.
$compartment = "2";
$files = glob("/path/to/files/$compartment.*"); // Will find 2.txt, 2.php, 2.gif
// Process through each file in the list
// and output its extension
if (count($files) > 0)
foreach ($files as $file)
{
$info = pathinfo($file);
echo "File found: extension ".$info["extension"]."<br>";
}
else
echo "No file name exists called $compartment. Regardless of extension."
by the way, what you are doing above is crying for a loop. Don’ repeat your code blocks, but wrap one of them into this:
$compartments = array(1, 3, 6, 9); // or whichever compartments
// you wish to run through
foreach ($compartments as $compartment)
{
..... insert code here .......
}
answered Jul 8, 2010 at 9:29
2
Look up:
- glob — Find pathnames matching a pattern
- fnmatch — Match filename against a pattern
- pathinfo — Returns information about a file path
w3spi
4,2909 gold badges46 silver badges80 bronze badges
answered Jul 8, 2010 at 9:31
GordonGordon
311k73 gold badges533 silver badges556 bronze badges
0
Хорошим примером использования рекурсии, может послужить поиск файла в папке и всем вложенным подпапкам.
Для поиска файла, достаточно перебрать все файлы во всех папках и сравнить название файла с искомым. И в случае совпадения добавить путь до файла в массив найденных фалов.
$folderName = ABSPATH; // в какой папке ищем $fileName = "xml"; // что ищем $found = search_file( $folderName, $fileName ); print_r( $found ); /* Вернет: Array ( [0] => /home/example.com/xmlrpc.php [1] => /home/example.com/wp-includes/class-wp-xmlrpc-server.php [2] => /home/example.com/wp-includes/wlwmanifest.xml ) */ /** * Поиск файла по имени во всех папках и подпапках * @param string $folderName - пусть до папки * @param string $fileName - искомый файл * @return array Массив найденных файлов. */ function search_file( $folderName, $fileName ){ $found = array(); $folderName = rtrim( $folderName, '/' ); $dir = opendir( $folderName ); // открываем текущую папку // перебираем папку, пока есть файлы while( ($file = readdir($dir)) !== false ){ $file_path = "$folderName/$file"; if( $file == '.' || $file == '..' ) continue; // это файл проверяем имя if( is_file($file_path) ){ // если имя файла искомое, то вернем путь до него if( false !== strpos($file, $fileName) ) $found[] = $file_path; } // это папка, то рекурсивно вызываем search_file elseif( is_dir($file_path) ){ $res = search_file( $file_path, $fileName ); $found = array_merge( $found, $res ); } } closedir($dir); // закрываем папку return $found; }
В данном уроке мы разберемся с типовой задачей, которая возникает во время работы над проектом 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, следует использовать код:
<?php $filelist = glob("*.txt");
Если вывести переменную $filelist
, то получим:
array ( 0 => 'article.txt', 1 => 'text.txt' )
Если нужен список файлов и директорий, имена которых начинаются на “te”, то код будет выглядеть так:
<?php $filelist = glob("te*");
А вывод имеет вид:
array ( 0 => 'test.dat', 1 => 'text.txt' )
А для получения списка только директорий с именами, содержащих “ma”, используем код:
<?php $filelist = glob("*ma*", GLOB_ONLYDIR);
Последний пример выведет:
Обратите внимание, что в последнем примере использован флаг GLOB_ONLYDIR
в качестве второго параметра функции. Поэтому файл master.dat
исключен из списка. Хотя функция glob()
очень проста в использовании, иногда она недостаточно гибкая. Например, нет флага для получения только файлов (без директорий), которые соответствуют шаблону.
Используем opendir()
, readdir()
, и closedir()
.
Второй подход к получению списка файлов и директорий, который мы обсудим, заключается в использовании функций opendir()
, readdir()
, и closedir()
.
Функция opendir()
открывает директорию и возвращает дескриптор соединения. Как только дескриптор получен, можно использовать функцию readdir()
. С каждым обращением данная функция выдает имя следующего файла или директории внутри открытого каталога. Если все имена уже были перечислены, функция возвращает false. Для закрытия дескриптора используется функция closedir()
.
В отличие от использования функции glob()
, данный подход сложнее, так как у вас нет параметров, которые помогают фильтровать список возвращаемых имен файлов и директорий. Вы должны выполнить фильтрацию самостоятельно, чтобы получить нужный результат.
Ниже приведенный пример возвращает список имен файлов и директорий начинающихся на “te”:
<?php $filelist = array(); if ($handle = opendir(".")) { while ($entry = readdir($handle)) { if (strpos($entry, "te") === 0) { $filelist[] = $entry; } } closedir($handle); }
При выполнении выше приведенного кода, переменная $entry
будет содержать такие включения, как “.” и “..”. Это две виртуальные директории, которые имеются в каждом каталоге файловой системы. Они представляют текущий каталог и родительский каталог соответственно.
Второй пример выводит только файлы, содержащиеся в заданном каталоге.
<?php $filelist = array(); if ($handle = opendir(".")) { while ($entry = readdir($handle)) { if (is_file($entry)) { $filelist[] = $entry; } } closedir($handle); }
Пример выдаст следующее:
array ( 0 => 'article.txt', 1 => 'master.dat', 2 => 'script.php', 3 => 'test.dat', 4 => 'text.txt' )
Использование scandir()
В завершение представим функцию scandir()
. Она имеет только один обязательный параметр: путь для чтения. Функция возвращает массив файлов и директорий, расположенных по указанному пути. Для получения списка файлов и директорий по определенному критерию нужно выполнить дополнительную фильтрацию. С другой стороны, решение получается более кратким и не требует управления дескрипторами.
Данный пример показывает, как получить список файлов и каталогов, имена которых начинаются на “te”:
<?php $entries = scandir("."); $filelist = array(); foreach($entries as $entry) { if (strpos($entry, "te") === 0) { $filelist[] = $entry; } }
Воспользуемся итераторами 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
используется для фильтрации результата на основе регулярных выражений.
<?php $iterator = new FilesystemIterator("."); $filelist = array(); foreach($iterator as $entry) { if (strpos($entry->getFilename(), "te") === 0) { $filelist[] = $entry->getFilename(); } }
Выше приведенный код выдаст результат, аналогичный предыдущим примерам.
Второй пример с применением RegexIterator
:
<?php $iterator = new FilesystemIterator("."); $filter = new RegexIterator($iterator, '/t.(php|dat)$/'); $filelist = array(); foreach($filter as $entry) { $filelist[] = $entry->getFilename(); }
Он будет выводить:
array ( 0 => 'script.php', 1 => 'test.dat' )
RecursiveDirectoryIterator
Итератор RecursiveDirectoryIterator
обеспечивает интерфейс для рекурсивного прохода по директориям файловой системы. Он имеет несколько полезных методов, таких как getChildren()
и hasChildren()
, которые возвращают итератор для текущего места, если это директория, и проверяют, является ли текущая точка входа директорией. Следующий пример демонстрирует использование RecursiveDirectoryIterator
и getChildren()
. Результат будет такой же, как и в предыдущих примерах.
<?php $iterator = new RecursiveDirectoryIterator('.'); $filter = new RegexIterator($iterator->getChildren(), '/t.(php|dat)$/'); $filelist = array(); foreach($filter as $entry) { $filelist[] = $entry->getFilename(); }
GlobIterator
Итератор GlobIterator
выполняет проход по файловой системе также, как и функция glob()
. Первый параметр может включать шаблон для имени. Пример демонстрирует использование GlobIterator
с тем же результатом, что и ранее.
<?php $iterator = new GlobIterator("te*"); $filelist = array(); foreach($iterator as $entry) { $filelist[] = $entry->getFilename(); }
Заключение
В данном уроке демонстрируется использование различных подходов для достижение одинаковой цели: получение списка файлов и директорий. Следует запомнить следующие ключевые моменты:
- Функция
glob()
является встроенным решением, но она недостаточно гибкая. - Решение на основе
opendir()
,readdir()
, иclosedir()
более сложное и требует дополнительной фильтрации, но оно более гибкое. - Функция
scandir()
требует дополнительной фильтрации, но работает без обработки дескриптора. - Если вы используете подход ООП, то следует применять библиотеку SPL. Дополнительно вы можете расширить классы своим функционалом.
- Итератор
GlobIterator
имеет функцию предварительной фильтрации, а другие используютRegexIterator
.