Как исключить типы файлов из цикла Directory Iterator - PullRequest
3 голосов
/ 22 августа 2011

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

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

$scan_it = new RecursiveDirectoryIterator("/example_dir");

 foreach(new RecursiveIteratorIterator($scan_it) as $file) {

  echo $file;
  }

Ответы [ 7 ]

11 голосов
/ 22 августа 2011

Обновление: Итак, я идиот. 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;
}
4 голосов
/ 08 апреля 2014

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

$iterator = new \RecursiveDirectoryIterator(getcwd(), \RecursiveDirectoryIterator::SKIP_DOTS);

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

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

 foreach($iterator as $file) {
   echo $file;
 }
2 голосов
/ 31 января 2013

Кросс-постинг оригинальный ответ ( также в этот вопрос ) -

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

Без предварительного фильтра:

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

Предварительный фильтр Glob:

$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);
1 голос
/ 08 января 2016

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

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

<?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
    }
}



?>
1 голос
/ 22 августа 2011

Расширяя другие ответы, вы можете сделать фильтрацию более понятным способом, специализируя RecursiveFilterIterator. Например, подход на основе 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, если хотите использовать подход, основанный на имени файла.

0 голосов
/ 13 мая 2019

Вот как бы я это сделал:

// Get all files ending with ".php" in folder
$folder = __DIR__ . '/example_dir';

$iterator = new RegexIterator(
    new DirectoryIterator($folder), // You can change this to RecursiveDirectoryIterator it you want
    '/\.php$/i',
    RegexIterator::MATCH
);

/** @var SplFileInfo $field_file */
foreach ($r_iterator as $field_file) {
    echo $field_file->getPathname();
}
0 голосов
/ 22 августа 2011

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

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

Код

<?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)))
...