4

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

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

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

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

  echo $file;
  }
4

7 回答 7

13

更新: 好的,所以我是个白痴。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;
}
于 2011-08-21T22:13:35.027 回答
5

从 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;
 }
于 2014-04-08T11:08:04.993 回答
2

交叉发布原始答案也在 这个问题中) -

变成glob迭代器似乎比编写自定义更容易进行预过滤FilterIterator。另请注意,FilterIterator在迭代期间仍会逐步执行每个项目,只是忽略它,而 glob 似乎没有。 但是glob似乎包含而不是排除,因此可能不适合您的情况。

无前置过滤器:

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

全局预过滤器:

$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,而globexample 只是磁盘路径。


示例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);
于 2013-01-31T02:38:45.717 回答
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如果您想使用基于文件名的方法,您可以使用。

于 2011-08-21T23:12:56.973 回答
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
    }
}



?>
于 2016-01-08T16:38:42.813 回答
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)))
于 2011-08-21T22:26:27.130 回答
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();
}
于 2019-05-13T02:42:05.623 回答