PHP 中的 RecursiveDirectoryIterator,在 foreach 中获取每个目录两次
RecursiveDirectoryIterator in PHP, getting each directory twice in foreach
我有以下非常简单的 RecursiveDirectoryIterator 代码:
$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
的默认行为是仅遍历 "leaf" 项(即不包含更多项的项)而不是所有项,从而有效地跳过目录。
因此,您需要告诉 RecursiveIteratorIterator
使用不同的模式,而不是默认的 "leaves only" 模式:"self first" 或 "child first" 之一。
$iter = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
回到您的原始代码,您可以通过回显 $item->getPathname()
(或者简单地回显 $item
在这里工作)来查看发生了什么。这将向您显示您需要跳过的 "dot directories"。
我有以下非常简单的 RecursiveDirectoryIterator 代码:
$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
的默认行为是仅遍历 "leaf" 项(即不包含更多项的项)而不是所有项,从而有效地跳过目录。
因此,您需要告诉 RecursiveIteratorIterator
使用不同的模式,而不是默认的 "leaves only" 模式:"self first" 或 "child first" 之一。
$iter = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
回到您的原始代码,您可以通过回显 $item->getPathname()
(或者简单地回显 $item
在这里工作)来查看发生了什么。这将向您显示您需要跳过的 "dot directories"。