Как исключить типы файлов из цикла каталогов Iterator

Простой итератор каталога, который является рекурсивным и показывает все файлы и каталоги / подкаталоги.

Я не вижу встроенной функции для исключения определенных типов файлов, например, в следующем примере я не хочу выводить файлы с изображениями, такие как .jpg , .png и т. Д. Я знаю, что есть несколько способов сделать это , ища советы, по которым было бы лучше.

 $scan_it = new RecursiveDirectoryIterator("/example_dir"); foreach(new RecursiveIteratorIterator($scan_it) as $file) { echo $file; } 

Related of "Как исключить типы файлов из цикла каталогов Iterator"

Обновление: Хорошо, я идиот. PHP имеет встроенный для этого: pathinfo()

Попробуй это:

 $filetypes = array("jpg", "png"); $filetype = pathinfo($file, PATHINFO_EXTENSION); if (!in_array(strtolower($filetype), $filetypes)) { echo $file; } 

Оригинальный ответ:

Почему бы просто не запустить substr() в имени файла и посмотреть, совпадает ли он с расширением типа файла, который вы хотите исключить:

 $scan_it = new RecursiveDirectoryIterator("/example_dir"); foreach(new RecursiveIteratorIterator($scan_it) as $file) { if (strtolower(substr($file, -4)) != ".jpg" && strtolower(substr($file, -4)) != ".jpg") { echo $file; } } 

Вы можете сделать это проще, используя регулярные выражения:

 if (!preg_match("/\.(jpg|png)*$/i", $file, $matches)) { echo $file; } 

Вы даже можете использовать массив для отслеживания типов файлов:

 $filetypes = array("jpg", "png"); if (!preg_match("/\.(" . implode("|", $filetypes) . ")*$/i", $file, $matches)) { echo $file; } 

Из PHP 5.4 можно использовать \ RecursiveCallbackFilterIterator

 $iterator = new \RecursiveDirectoryIterator(getcwd(), \RecursiveDirectoryIterator::SKIP_DOTS); $iterator = new \RecursiveCallbackFilterIterator( $iterator, function ($item) { return $item->getExtension() === 'php' ? true : false; } ); 

Теперь Iterator будет содержать только файлы PHP.

  foreach($iterator as $file) { echo $file; } 

Перекрестный отправку исходного ответа ( также в этом вопросе ) –

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

Нет предварительной фильтрации:

 $dir_iterator = new DirectoryIterator($dir); $paginated = new LimitIterator($dir_iterator, $page * $perpage, $perpage); 

Glob prefilter:

 $dir_glob = $dir . '/*.{jpg,gif,png}'; $dir_iterator = new ArrayObject(glob($dir_glob, GLOB_BRACE)); // need to get iterator $dir_iterator = $dir_iterator->getIterator(); $paginated = new LimitIterator($dir_iterator, $page * $perpage, $perpage); 

Тогда сделайте свое дело:

 foreach ($paginated as $file) { ... } 

Обратите внимание, что в случае примера DirectoryIterator $file будет экземпляром SplFileInfo , тогда как пример glob – это только путь к диску.


Пример расширения FilterIterator

 class ExtensionFilterIterator extends FilterIterator { private $filter; public function __construct(Iterator $iterator , $filter) { parent::__construct($iterator); $this->filter = $filter; } // the meat and potatoes public function accept() { $current = $this->getInnerIterator()->current(); ### global $counter; ### print_r(array($counter++, $current)); // this proves it goes through the whole thing, even with limit // do your comparison // assume path if( is_string($current) ) { $extension = end( explode('.', $current) ); } // assume DirectoryIterator else { // $ext = $fileinfo->getExtension(); // http://www.php.net/manual/en/class.splfileinfo.php $extension = pathinfo($current->getFilename(), PATHINFO_EXTENSION); // < PHP 5.3.6 -- http://www.php.net/manual/en/splfileinfo.getextension.php } return ! in_array($extension,$this->filter); } } 

Применение:

 $dir_iterator = new ExtensionFilterIterator(new DirectoryIterator($dir), array('gif', 'jpg', 'png')); $paginated = new LimitIterator($dir_iterator, $page * $perpage, $perpage); 

Расширяясь по другим ответам, вы можете сделать фильтрацию более чистым способом, специализируясь на RecursiveFilterIterator . Например, finfo основе finfo :

 class MyRecursiveFilterIterator extends RecursiveFilterIterator { private $finfo; function __construct(RecursiveIterator $i) { $this->finfo = new finfo(FILEINFO_MIME_TYPE); parent::__construct($i); } /** * Filter out files with a MIME type of image/* */ public function accept() { $file = $this->current(); $filetype = $this->finfo->file($file); $type_parts = explode("/", $filetype, 2); $type = $type_parts[0]; return ("image" !== $type); } } $scan_it = new RecursiveDirectoryIterator("."); foreach (new RecursiveIteratorIterator( new MyRecursiveFilterIterator($scan_it)) as $file) { print ("$file\n"); } 

Аналогичным образом вы можете использовать RecursiveRegexIterator если вы хотите использовать подход на основе имени файла.

Я люблю примеры, и вот один

Я искал способ фильтровать расширение. Вы можете включать / исключать расширения.

 <?php $dir_iterator = new RecursiveDirectoryIterator("/path"); $iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST); // could use CHILD_FIRST if you so wish foreach ($iterator as $file) { echo $file, "\n"; } ?> 

$ file будет классом SplFileInfo, так что вы можете сделать мощный материал очень легко:

 <?php foreach ($iterator as $file) { if ($file->isFile()) { echo $file->getExtension(); //By this you are king and you can access more functions of SplFileInfo } } ?> 

Вы можете использовать функцию finfo_file PHP, которая возвращает информацию о файле.

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

Код

 <?php $finfo = finfo_open(FILEINFO_MIME_TYPE); $scan_it = new RecursiveDirectoryIterator("/example_dir"); foreach(new RecursiveIteratorIterator($scan_it) as $file) { echo finfo_file($finfo, $file) . "<br/>"; } finfo_close($finfo); ?> 

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

 image/png directory image/png image/svg+xml 

редактировать

Таким образом, вы можете взять файлы без изображения с чем-то вроде этого:

 if(!preg_match("/image.*/",finfo_file($finfo, $file)))