Как найти файл по имени php

Для поиска файлов на сервере хорошо подходит функция 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 со следующим содержимым:

Содержимое папки 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().

Другие публикации

Использование API Яндекс Диска на PHP

Можно найти множество применений Яндекс Диска на своем сайте, например, хранение бекапов и отчетов, обновление прайсов,…

Работа с FTP в PHP

Протокол FTP – предназначен для передачи файлов на удаленный хост. В PHP функции для работы с FTP как правило всегда доступны и не требуется установка дополнительного расширения.

Загрузка файлов на сервер PHP

В статье приведен пример формы и php-скрипта для безопасной загрузки файлов на сервер, возможные ошибки и рекомендации при работе с данной темой.

Пример парсинга html-страницы на phpQuery

phpQuery – это удобный HTML парсер взявший за основу селекторы, фильтры и методы jQuery, которые позволяют…

Поиск похожих текстов в базе данных MySQL + PHP

Один из вариантов поиска похожих статей в базе данных основан на схождении слов в двух текстах.

Список MIME типов

Ниже приведён список 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 Cheeseman's user avatar

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

Pekka's user avatar

2

Look up:

  • glob — Find pathnames matching a pattern
  • fnmatch — Match filename against a pattern
  • pathinfo — Returns information about a file path

w3spi's user avatar

w3spi

4,2909 gold badges46 silver badges80 bronze badges

answered Jul 8, 2010 at 9:31

Gordon's user avatar

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.

Добавить комментарий