How to do a postorder enumeration of a directory?

How do I accomplish a postorder enumeration of a directory (that is, get subdirectories before the parents)?

Normally I would use FileManager.enumerator(at:includingPropertiesForKeys:options:errorHandler:) for enumeration. And there is a DirectoryEnumerationOptions named includesDirectoriesPostOrder.

Unfortunately it does not seem to work. If I create the enumerator like this:

FileManager.default.enumerator(at: url,
    includingPropertiesForKeys: resourceKeys,
    options: [.skipsPackageDescendants,
        .skipsHiddenFiles,
        .includesDirectoriesPostOrder])

The enumerator does not provide the results postorder. And in fact if you check the isEnumeratingDirectoryPostOrder, it returns false.

Am I using this incorrectly, or is it just broken? Is there some other way to accomplish this? I see that CFURLEnumerator has a similar option, though I don't know if it works any better. Plus I would rather not wrestle with Core Foundation code if I can avoid it.

Answered by JWWalker in 793000022

I tried it in Objective-C, and it does work, but it's not super obvious how it works. If you look up NSDirectoryEnumerationIncludesDirectoriesPostOrder in the header, comments say:

NSDirectoryEnumerationIncludesDirectoriesPostOrder causes the NSDirectoryEnumerator to enumerate each directory a second time after all of its contained files have been enumerated. Use NSDirectoryEnumerator.isEnumeratingDirectoryPostOrder to differentiate a post-order enumerated directory from a pre-order one.

What this means is that the enumerator visits a directory, then visits the contents of the directory, and then visits the directory again, and the second time, the isEnumeratingDirectoryPostOrder property of the enumerator is true.

Maybe you should file a feedback about the documentation.

Could this help: https://stackoverflow.com/questions/34440512/enumerating-directories-iteratively-in-postorder

or at least give a direction for searching ?

Just to follow-up on this, the CFURLEnumerator version of this does actually work correctly, so I think there is a bug in FileManager.DirectoryEnumerator. I'll be filing a feedback.

Accepted Answer

I tried it in Objective-C, and it does work, but it's not super obvious how it works. If you look up NSDirectoryEnumerationIncludesDirectoriesPostOrder in the header, comments say:

NSDirectoryEnumerationIncludesDirectoriesPostOrder causes the NSDirectoryEnumerator to enumerate each directory a second time after all of its contained files have been enumerated. Use NSDirectoryEnumerator.isEnumeratingDirectoryPostOrder to differentiate a post-order enumerated directory from a pre-order one.

What this means is that the enumerator visits a directory, then visits the contents of the directory, and then visits the directory again, and the second time, the isEnumeratingDirectoryPostOrder property of the enumerator is true.

Maybe you should file a feedback about the documentation.

I want to pick up on this from a comment:

I would rather use built-in functionality if possible

Why?

Seriously. Write it yourself. It will do exactly what you want with no confusion about whether it is borked or just "working as intended".

Oh, and it will be portable, and it won't get deprecated in 2 years time.

How to do a postorder enumeration of a directory?
 
 
Q