Простой итератор каталога, который является рекурсивным и показывает все файлы и каталоги / подкаталоги.
Я не вижу встроенной функции для исключения определенных типов файлов, например, в следующем примере я не хочу выводить файлы с изображениями, такие как .jpg
, .png
и т. Д. Я знаю, что есть несколько способов сделать это , ища советы, по которым было бы лучше.
$scan_it = new RecursiveDirectoryIterator("/example_dir"); foreach(new RecursiveIteratorIterator($scan_it) as $file) { echo $file; }
Обновление: Хорошо, я идиот. 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)))