Компонент Finder
Дата обновления перевода 2024-07-03
Компонент Finder
Компонент Finder находит файлы и каталоги, основываясь на разных критериях (имени, размере файла, времени изменения и др.) через текучий интерфейс.
Установка
1
$ composer require symfony/finder
Note
Если вы устанавливаете этот компонент вне приложения Symfony, вам нужно
подключить файл vendor/autoload.php
в вашем коде для включения механизма
автозагрузки классов, предоставляемых Composer. Детальнее читайте в
этой статье.
Применение
Класс Finder находит файлы и/или каталоги:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
use Symfony\Component\Finder\Finder;
$finder = new Finder();
// найти все файлы текущего каталога
$finder->files()->in(__DIR__);
// проверить, есть ли результаты поиска
if ($finder->hasResults()) {
// ...
}
foreach ($finder as $file) {
$absoluteFilePath = $file->getRealPath();
$fileNameWithExtension = $file->getRelativePathname();
// ...
}
Переменная $file
является экземпляром SplFileInfo,
который расширяет собственный SplFileInfo PHP, чтобы предоставить методы для работы
с относительными путями.
Caution
Объект Finder
не перезагружает внутреннее состояние автоматически. Это
означает, что вам нужно создать новый экземпляр, если вы не хотите получить
смешнанный результат.
Поиск файлов и каталогов
Компонент предоставляет множество методов для определения критериев поиска. Все они могут быть в цепочке, так как реализуют текучий интерфейс.
Локация
Локация - единственный обязательный критерий. Она сообщает Finder, какой каталог использовать для поиска:
1
$finder->in(__DIR__);
Искать в нескльких локациях, изменяя вызов на in():
1 2 3 4 5
// искать внутри *обоих* каталогов
$finder->in(array(__DIR__, '/elsewhere'));
// то же, что и выше
$finder->in(__DIR__)->in('/elsewhere');
Используйте *
в качестве символа-заполнителя, чтобы искать в каталогах, соответствующих
паттерну (каждый паттерн должен разрешать хотя бы один путь каталога):
1
$finder->in('src/Symfony/*/*/Resources');
Исключите каталоги, совпадающие с методом exclude():
1 2
// каталоги, переданные в качестве аргумента, должны быть связаны с теми, что определены в методе in()
$finder->in(__DIR__)->exclude('ruby');
Также возможно игнорировать каталоги, на чтение которых у вас нет разрешения:
1
$finder->ignoreUnreadableDirs()->in(__DIR__);
Так как Finder использует PHP итераторы, вы можете передать любой URL,
поддерживаемый PHP-оберткой для протоколов типа URL (ftp://
, zlib://
, etc.):
1 2 3 4 5
// всегда добавляйте закрывающий слеш, когда ищете dir корна FTP
$finder->in('ftp://example.com/');
// вы можете также искать в каталоге FTP
$finder->in('ftp://example.com/pub/');
И это также работает с потоками, определёнными пользователями:
1 2 3 4 5 6 7 8 9 10 11
use Symfony\Component\Finder\Finder;
// зарегистрировать обертку 's3://' с официальным AWS SDK
$s3Client = new Aws\S3\S3Client([/* config options */]);
$s3Client->registerStreamWrapper();
$finder = new Finder();
$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
foreach ($finder->in('s3://bucket-name') as $file) {
// ... сделать что-то с файлом
}
See also
Прочтите документацию PHP-потоки, чтобы узнать, как создавать собственные потоки.
Файлы или каталоги
По умолчанию, Finder возвращает и файлы, и каталоги. Если вам нужны только файлы, или только каталоги, используйте методы files() и directories():
1 2 3 4 5
// искать только файлы; игнорировать каталоги
$finder->files();
// искать только каталоги; игнорировать файлы
$finder->directories();
Если вы хотите следовать символьным ссылкам, используйте метод followLinks()
:
1
$finder->files()->followLinks();
Файлы контроля версий
Системы контроля версий (или сокращённо "VCS"), такие как Git и Mercurial,
создают специальные файлы для хранения своих метаданных. Эти файлы игнорируются
при поиске файлов и каталогов по умолчанию, но вы можете изменить это методом
ignoreVCS()
:
1
$finder->ignoreVCS(false);
Если поисковый каталог и его подкаталоги содержат файлы .gitignore
, вы
можете повторно использовать эти правила, чтобы исключить файлы и каталоги из
результатов, методом ignoreVCSIgnored():
1 2
// исключить files/directories, совпадающие с паттернами .gitignore
$finder->ignoreVCSIgnored(true);
Правила каталога всегда главенствуют над правилами родительских каталогов.
Note
Git ищет файлы .gitignore
, начиная с корневого каталога хранилица.
Поведение Symfony Finder отличается - он ищет файлы .gitignore
, начиная
с каталога, используемого для поиска файлов/каталогов. Чтобы соответствовать
поведению Git, вам нужно ясно искать из корня хранилища Git.
Имя файла
Найдите файлы по имени методом name():
1
$finder->files()->name('*.php');
Метод name()
принимает глобальные выражения, строки, регулярные выражения
и массивы глобальных или регулярных выражений:
1
$finder->files()->name('/\.php$/');
Множество имен файлов может быть определено путем создания цепочки вызовов или передачи массива:
1 2 3 4
$finder->files()->name('*.php')->name('*.twig');
// то же, что и выше
$finder->files()->name(['*.php', '*.twig']);
Метод notName()
исключает файлы, совпадающие со схемой:
1
$finder->files()->notName('*.rb');
Множество имен файлов может быть исключено путем создания цепочки вызовов или передачи массива:
1 2 3 4
$finder->files()->notName('*.rb')->notName('*.py');
// то же, что и выше
$finder->files()->notName(['*.rb', '*.py']);
Содержание файла
Найдите файлы по содержанию, методом contains():
1
$finder->files()->contains('lorem ipsum');
Метод contains()
принимает строки или регулярные выражения:
1
$finder->files()->contains('/lorem\s+ipsum$/i');
Метод notContains()
исключает файлы, содержащие заданный паттерн:
1
$finder->files()->notContains('dolor sit amet');
Путь
Найдите файлы и папки по пути, методом path():
1 2 3 4
// сопоставляет файлы, содержащие "data" где-либо в их путях (файлах или каталогах)
$finder->path('data');
// например, это будет соответстсовать data/*.xml и data.xml, если они существуют
$finder->path('data')->name('*.xml');
Используйте слеш вправо (т.e. /
) в качестве разделителя каталогов на всех
платформах, включая Windows. Компонент проведет необходимые преобразования внутренне.
Метод path()
принимает строку, регулярное выражение или массив строк или
регулярных выражений:
1 2
$finder->path('foo/bar');
$finder->path('/^foo\/bar/');
Множество путей может быть определено путем создания цепочки вызовов или передачи массива:
1 2 3 4
$finder->path('data')->path('foo/bar');
// то же, что и выше
$finder->path(['data', 'foo/bar']);
Внутренне, строки преобразуются в регулярные выражения, экранируя слеши и добавляя разграничители:
??????????? ?????? | ???????????? ?????????? ????????? |
---|---|
dirname |
/dirname/ |
a/b/c |
/a\/b\/c/ |
Метод notPath() исключает файлы по пути:
1
$finder->notPath('other/dir');
Множество путей можно исключить путем создания цепочки вызовов или передачи массива:
1 2 3 4
$finder->notPath('first/dir')->notPath('other/dir');
// то же, что и выше
$finder->notPath(['first/dir', 'other/dir']);
Размер файла
Найдите файлы по размеру, методом size():
1
$finder->files()->size('< 1.5K');
Ограничьте по диапазону размера, создав цепочку вызовов или передав массив:
1 2 3 4
$finder->files()->size('>= 1K')->size('<= 2K');
// то же, что и выше
$finder->files()->size(['>= 1K', '<= 2K']);
Оператор сравнения может быть чем-либо из следующего: >
, >=
, <
, <=
,
==
, !=
.
Целевое значение может использовать величины килобайтов (k
, ki
), мегабайтов
(m
, mi
), или гигабайтов (g
, gi
). Те, что имеют суффикс i
, используют
соответствующую версию 2**n
в соответствии со стандартом IEC.
Дата файла
Найдите файлы по датам последних изменений, методом date() :
1
$finder->date('since yesterday');
Ограничьте по диапазноу данных путем создания цепочки вызовов или передачи массива:
1 2 3 4
$finder->date('>= 2018-01-01')->date('<= 2018-12-31');
// то же, что и выше
$finder->date(['>= 2018-01-01', '<= 2018-12-31']);
Оператор сравнения может быть любым из следующих: >
, >=
, <
, <=
,
==
. Вы можете также использовать since
или after
в качестве дополнительного
имени >
, и until
или before
в качестве дополнительного имени <
.
Целевое значение может быть любыми данными, поддерживаемыми функцией 3e58f474762cc1c5095e917255f3d98f65e2bfef.
Глубина каталога
По умолчанию, Finder траверсирует каталоги в обратном порядке. Ограничьте глубину траверсирования методом depth():
1 2 3
// это будет рассматривать только файлы/каталоги, которые являются прямыми дочерними
$finder->depth('== 0');
$finder->depth('< 3');
Ограничьте по диапазону глубины путем создания цепочки вызовов или передачи массива:
1 2 3 4
$finder->depth('> 2')->depth('< 5');
// то же, что и выше
$finder->depth(['> 2', '< 5']);
Пользовательское фильтрование
Чтобы отфильтровать результаты по собственной стратегии, используйте filter():
1 2 3 4 5 6 7 8
$filter = function (\SplFileInfo $file)
{
if (strlen($file) > 10) {
return false;
}
};
$finder->files()->filter($filter);
Метод filter()
берёт Closure в качестве аргумента. Для каждого совпадающего
файла, он вызываетя с файлом SplFileInfo в
качестве экземпляра. Файл исключается из набора результатов, если замыкание возвращает
false
.
Метод filter()
содержит второй необязательный аргумент для обрезки каталогов.
Если установить значение true
, этот метод полностью пропускает исключенные каталоги
вместо того, чтобы обходить всю структуру файлов/каталогов и исключать их позже. При
использовании замыкания, верните false
для каталогов, которые вы хотите обрезать.
Раннее обрезание каталогов может значительно повысить производительность в зависимости от сложности иерархии файлов/каталогов и количества исключаемых каталогов.
Сортировка результатов
Отсортируйте результаты по имени или типу (сначала каталоги, потом - файлы):
1 2 3 4 5
$finder->sortByName();
$finder->sortByCaseInsensitiveName();
$finder->sortByExtension();
$finder->sortBySize();
$finder->sortByType();
Tip
По умолчанию, метод sortByName()
использует PHP-функцию strcmp
(например, file1.txt
, file10.txt
, file2.txt
). Передайте true
в
качестве ее аргумента, чтобы использовать вместо этого алгоритмы
природного порядка сортировки PHP (например, file1.txt
, file2.txt
,
file10.txt
).
Метод sortByCaseInsensitiveName()
использует нечувствительную к регистру PHP-функцию
strcasecmp. Передайте true
как её аргумент, чтобы исполььзовать вместо
этого нечувствительный к регистру PHP-алгоритм природного порядка сортировки (т.е. PHP-функцию
strnatcasecmp).
Отсортируйте файлы и каталоги по последнему доступу, изменению или времени изменения:
1 2 3 4 5
$finder->sortByAccessedTime();
$finder->sortByChangedTime();
$finder->sortByModifiedTime();
Вы также можете определить собственный алгоритм сортировки методом sort()
:
1 2 3
$finder->sort(function (\SplFileInfo $a, \SplFileInfo $b): int {
return strcmp($a->getRealPath(), $b->getRealPath());
});
Вы можете поменять порядок любой сортировки, используя метод reverseSorting()
:
1 2
// результаты будут отсортированы "от Z до A" вместо "от A до Z" по умолчанию
$finder->sortByName()->reverseSorting();
Note
Заметьте, что методы sort*
должны получить все совпадающие элементы, чтобы
работать. Для больших итераторов это будет медленно.
Преобразование результатов в массивы
Экземпляр Finder - это PHP-класс IteratorAggregate. Поэтому,
в дополнение к итерации foreach
поверх результатов Finder, вы также
можете преобразовать их в массив с помощью функции iterator_to_array,
или получить количество объектов с помощью iterator_count.
Если вы вызовете метод in() более
одного раза, чтобы произвести поиск по множеству локаций, передайте false
в качестве второго параметра iterator_to_array, чтобы избежать
проблем (отдельный итератор создается для каждой локации, и если вы не передадите
false
к iterator_to_array, используются ключи наборов результатов,
и некоторые из них могут быть дублированы, а их значения - переопределены).
Чтение содержания возвращённых файлов
Содержание возвращённых файлов можно прочитать с помощью getContents():
1 2 3 4 5 6 7 8 9 10
use Symfony\Component\Finder\Finder;
$finder = new Finder();
$finder->files()->in(__DIR__);
foreach ($finder as $file) {
$contents = $file->getContents();
// ...
}