Ответ 1
Есть несколько разных способов сделать что-то вроде этого, я дам вам два быстрых подхода: быстро и грязно, по сравнению с дольше и менее грязными (хотя это пятница, так что мы позволили немного сходить с ума).
1. Быстрый (и грязный)
Это включает в себя просто запись регулярного выражения (может быть разделено на несколько) для использования для фильтрации коллекции файлов одним быстрым махом.
(Только две прокомментированные строки действительно важны для концепции.)
$directory = new RecursiveDirectoryIterator(__DIR__);
$flattened = new RecursiveIteratorIterator($directory);
// Make sure the path does not contain "/.Trash*" folders and ends eith a .php or .html file
$files = new RegexIterator($flattened, '#^(?:[A-Z]:)?(?:/(?!\.Trash)[^/]+)+/[^/]+\.(?:php|html)$#Di');
foreach($files as $file) {
echo $file . PHP_EOL;
}
В этом подходе есть ряд проблем, хотя быстро реализовать это просто однострочный (хотя регулярное выражение может быть болью для расшифровки).
2. Менее быстрые (и менее грязные)
Более многоразовый подход заключается в создании нескольких настраиваемых фильтров (с использованием регулярных выражений или любого другого, что вам нравится!), чтобы уничтожить список доступных элементов в начальном RecursiveDirectoryIterator
до тех пор, пока вы не захотите. Ниже приведен только один пример, написанный быстро для вас, расширения RecursiveRegexIterator
.
Начнем с базового класса, основной задачей которого является удерживание регулярного выражения, которое мы хотим отфильтровать, все остальное отложено обратно на RecursiveRegexIterator
. Обратите внимание, что класс abstract
, поскольку он фактически не делает ничего полезного: фактическая фильтрация должна выполняться двумя классами, которые будут расширять этот. Кроме того, его можно назвать FilesystemRegexFilter
, но нет ничего, что вынуждало бы (на этом уровне) фильтровать классы, связанные с файловой системой (я бы выбрал лучшее имя, если бы я не был настолько сонным).
abstract class FilesystemRegexFilter extends RecursiveRegexIterator {
protected $regex;
public function __construct(RecursiveIterator $it, $regex) {
$this->regex = $regex;
parent::__construct($it, $regex);
}
}
Эти два класса - это очень простые фильтры, действующие соответственно на имя файла и имя каталога.
class FilenameFilter extends FilesystemRegexFilter {
// Filter files against the regex
public function accept() {
return ( ! $this->isFile() || preg_match($this->regex, $this->getFilename()));
}
}
class DirnameFilter extends FilesystemRegexFilter {
// Filter directories against the regex
public function accept() {
return ( ! $this->isDir() || preg_match($this->regex, $this->getFilename()));
}
}
Чтобы реализовать их на практике, следующие повторяются по каталогу, в котором находится script (не стесняйтесь редактировать это!) и отфильтровывайте папки .Trash
(убедившись, что имена папок совпадают с специально созданным регулярным выражением) и принимают только файлы PHP и HTML.
$directory = new RecursiveDirectoryIterator(__DIR__);
// Filter out ".Trash*" folders
$filter = new DirnameFilter($directory, '/^(?!\.Trash)/');
// Filter PHP/HTML files
$filter = new FilenameFilter($filter, '/\.(?:php|html)$/');
foreach(new RecursiveIteratorIterator($filter) as $file) {
echo $file . PHP_EOL;
}
Особо следует отметить, что, поскольку наши фильтры рекурсивные, мы можем поиграть с тем, как их перебирать. Например, мы могли бы легко ограничиться только сканированием до 2 уровней (включая начальную папку), выполнив следующие действия:
$files = new RecursiveIteratorIterator($filter);
$files->setMaxDepth(1); // Two levels, the parameter is zero-based.
foreach($files as $file) {
echo $file . PHP_EOL;
}
Также очень легко добавлять еще больше фильтров (путем создания дополнительных классов фильтрации с различными регулярными выражениями или путем создания новых классов фильтрации) для более специализированных задач фильтрации (например, размер файла, длина полного пути и т.д.)..).
P.S. Хмм, этот ответ немного болтает; Я старался держать его как можно более кратким (даже удаляя огромные кусочки супер-лепет). Извините, если чистый результат не дает ответа некогерентным.