【问题标题】:How to ignore directories using RecursiveIteratorIterator?如何使用 RecursiveIteratorIterator 忽略目录?
【发布时间】:2013-02-28 10:36:32
【问题描述】:

我尝试了几种方法来忽略文件系统上使用 RecursiveIteratorIterator 的某些目录。

举个例子,我想忽略以下目录:/cache

我的Iterator 看起来像这样:

//$dirname is root
$directory = new RecursiveDirectoryIterator($dirname);
$mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);

foreach ($mega as $fileinfo) {
 echo $fileinfo;
}

我已经能够使用pathinfo 忽略某些文件扩展名,例如这有效:

$filetypes = array("jpg", "png");
$filetype = pathinfo($fileinfo, PATHINFO_EXTENSION);

foreach ($mega as $fileinfo) {
    if (!in_array(strtolower($filetype), $filetypes)) {
    echo $fileinfo;
    }
}

当我使用PATHINFO_DIRNAME(在数组中使用适当的目录路径)尝试它时,它不起作用,没有错误,它只是不忽略目录。

我也尝试过使用FilterIterator,但无济于事,现在我想也许我应该使用RegexIterator

使用RecursiveIteratorIterator 忽略目录的最简单和最有效的方法是什么?


无效的实验。 使用PATHINFO_DIRNAME

$dirignore = array("cache", "cache2");
$directory = new RecursiveDirectoryIterator($dirname);
$mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
$dirtype = pathinfo($fileinfo, PATHINFO_DIRNAME); 

if (!in_array($dirtype), $dirignore)) {
echo $fileinfo;  //no worky still echo directories
}

使用FilterIterator(不确定这是如何工作的)

class DirFilter extends FilterIterator
{
    public function accept()
    {
        //return parent::current() != "..\cache\";

       $file = $this->getInnerIterator()->current();
       if ($file != "..\cache")
       return $file->getFilename();

      //also tried with same error as below
      //return !preg_match('/\cache', $file->getFilename());
    }
}

$directory= new RecursiveDirectoryIterator($dirname);
$directory = new DirFilter($directory); 
$mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
// loop

结果为@​​987654335@

【问题讨论】:

  • 您对 FilterIterator 的实验是什么样的?听起来你是在正确的轨道上。
  • 更新了 2 个不起作用的示例

标签: php iterator


【解决方案1】:

您的DirFilter 想要扩展RecursiveFilterIterator,因为它与递归迭代器一起使用。不这样做,是你的错误的原因。

class DirFilter extends RecursiveFilterIterator
{
    // …
}

下一步是弄清楚如何正确使用accept()。它应该返回一个truefalse 值,它指示当前项是应该包含(true)还是从迭代中排除(false)。从accept() 返回文件名不是您想要做的。

class DirFilter extends RecursiveFilterIterator
{
    public function accept()
    {
        $excludes = array("cache", "cache2");
        return !($this->isDir() && in_array($this->getFilename(), $excludes));
    }
}

能够传入排除目录的数组可能会很好。这需要更多代码,但可重用性更高。

class DirFilter extends RecursiveFilterIterator
{
    protected $exclude;
    public function __construct($iterator, array $exclude)
    {
        parent::__construct($iterator);
        $this->exclude = $exclude;
    }
    public function accept()
    {
        return !($this->isDir() && in_array($this->getFilename(), $this->exclude));
    }
    public function getChildren()
    {
        return new DirFilter($this->getInnerIterator()->getChildren(), $this->exclude);
    }
}

然后可以像这样使用此代码:

$directory = new RecursiveDirectoryIterator($dirname);
$filtered = new DirFilter($directory, $dirignore); 
$mega = new RecursiveIteratorIterator($filtered, …);

【讨论】:

  • 谢谢,这更有意义,但我所做的任何事情(使用两种方法)实际上似乎都没有过滤掉目录,这与我的PATHINFO_DIRNAME 示例中的情况相同(没有错误,目录仍然可见on output) ,我想知道这是否与在 Windows 上有关。我还在排除项中对路径 (D:\Sites\Bar12/wp-content\cache) 进行了硬编码,并尝试了几种变体和 nada。
  • 这听起来更像是一个 PEBKAC 错误。以上肯定会过滤这些目录,甚至在 Windows 上。
猜你喜欢
  • 2010-09-12
  • 2013-06-07
  • 2017-10-18
  • 2020-05-05
  • 1970-01-01
  • 2017-05-08
  • 2022-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多