我有以下非常简单的递归目录迭代器代码:
$dir = new RecursiveDirectoryIterator('/Users/yivi/test/', RecursiveDirectoryIterator::KEY_AS_PATHNAME);
$iter = new RecursiveIteratorIterator($dir);
foreach ($iter as $item) {
if ($item->isDir()) {
echo $item->getPath() . "'n";
$countd ++;
} else {
$count++;
}
}
echo "$count files and $count directories";
但产生以下输出:
/Users/yivi/Sites/test
/Users/yivi/Sites/test
/Users/yivi/Sites/test/01
/Users/yivi/Sites/test/01
/Users/yivi/Sites/test/02
/Users/yivi/Sites/test/02
/Users/yivi/Sites/test/03
/Users/yivi/Sites/test/03
/Users/yivi/Sites/test/03/ab
/Users/yivi/Sites/test/03/ab
/Users/yivi/Sites/test/03/cd
/Users/yivi/Sites/test/03/cd
40 files and 12 directories
当我退出循环时,我计算了每个目录两次(我得到双列表,$countd是 12,而不是 6)。
为什么它表现得这样?如何避免?
我尝试使用 RecursiveDirectoryIterator::SKIP_DOTS
作为标志,但随后它会跳过所有目录(但确实计算文件)。
(PHP 5.5)
TL;DR 使用 RecursiveIteratorIterator::SELF_FIRST
作为迭代模式,以及 RecursiveDirectoryIterator::SKIP_DOTS
标志。
您看到两行,因为$item
值用于"."和".."项,并且尝试使用SKIP_DOTS
是正确的,因为您很可能确实想跳过这些项。
但是,RecursiveIteratorIterator
的默认行为是仅迭代"叶"项(即不包含更多项的项目)而不是所有项,从而有效地跳过目录。
因此,您需要告诉RecursiveIteratorIterator
使用不同的模式,而不是默认的"仅离开"模式:"自我优先"或"孩子优先"模式之一。
$iter = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
回到原始代码,您可以通过回显$item->getPathname()
(或者简单地回显$item
在这里起作用)来查看发生了什么。 这将向您显示需要跳过的"点目录"。