如何从Directory Iterator循环中排除文件类型

时间:2011-08-21 22:05:33

标签: php file iterator directory spl

简单的目录迭代器,它是递归的并显示所有文件和目录/子目录。

我没有看到任何内置函数来排除某些文件类型,例如在以下示例中我不想输出任何与图像相关的文件,例如.jpg.png等。我知道有几种方法可以做到这一点,寻找最好的建议。

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

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

  echo $file;
  }

7 个答案:

答案 0 :(得分:10)

<强>更新 好的,所以我是个白痴。 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;
}

答案 1 :(得分:4)

从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;
 }

答案 2 :(得分:2)

交叉发布original answeralso in this question) -

glob转换为迭代器似乎比编写自定义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);

答案 3 :(得分:1)

扩展其他答案,您可以通过专门化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

答案 4 :(得分:1)

我喜欢这个例子,这里有一个

我正在寻找一种过滤扩展的方法。您可以包含/排除扩展名。

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



?>

答案 5 :(得分:0)

您可以使用返回文件信息的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)))

答案 6 :(得分:0)

这就是我要做的:

// 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();
}