简体   繁体   中英

RecursiveDirectoryIterator in PHP, getting each directory twice in foreach

I have the following very simple RecursiveDirectoryIterator code:

$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";

But produces the following output:

/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

By the time I exit the loop I counted each directory twice (I get the double listing and $countd is 12, instead of 6).

Why is it behaving this way? How to avoid it?

I've tried using RecursiveDirectoryIterator::SKIP_DOTS as a flag, but then it skips all directories (but does count the files).

(PHP 5.5)

TL;DR Use RecursiveIteratorIterator::SELF_FIRST as the iteration mode, along with the RecursiveDirectoryIterator::SKIP_DOTS flag.


You are seeing two lines because the $item values are for the "." and ".." items, and were right to try using SKIP_DOTS as you most likely do want to skip those items.

However, the default behaviour for the RecursiveIteratorIterator is to only iterate over "leaf" items (ie, items that don't contain more items) rather than everything, effectively skipping the directories.

So, you need to tell RecursiveIteratorIterator use a different mode, other than the default "leaves only" mode: one of "self first" or "child first".

$iter = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);

Back to your original code, you can see what's going on by echoing $item->getPathname() (or simply echoing $item would work here). That would show you the "dot directories" that you need to skip.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM