2013-03-12 174 views
4

我已经尝试了几种方法在文件系统上使用RecursiveIteratorIterator来忽略某些目录。如何使用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 

提斯结果Error: An instance of RecursiveIterator or IteratorAggregate creating it is required

+0

什么用FilterIterator你的实验是什么样子?这听起来像你在正确的轨道上。 – 2013-03-12 18:36:27

+0

更新了2个不起作用的示例 – Wyck 2013-03-12 19:03:14

回答

6

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, …); 
+0

感谢这使得更有意义,但我没有做任何事(使用这两种方法)实际上似乎过滤了目录,这与我的'PATHINFO_DIRNAME'示例中的情况相同(没有错误,目录在输出中仍然可见),我想知道这是否与在Windows上有关。我还对排除内容的路径('D:\ Sites \ Bar12/wp-content \ cache')进行了硬编码,并尝试了几种变体和nada。 – Wyck 2013-03-12 20:00:03

+0

这听起来更像是一个PEBKAC错误。以上将绝对过滤这些目录,甚至**在Windows上。 – salathe 2013-03-12 20:05:08

+0

你100%正确,错误的变量名称,欢呼声。 – Wyck 2013-03-12 20:17:00