使用以下代码片段递归映射当前目录的内容:
$files = new RecursiveIteratorIterator
(
new RecursiveDirectoryIterator('./',
FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS),
RecursiveIteratorIterator::SELF_FIRST
);
$files = array_values(array_map('strval', iterator_to_array($files)));
返回类似这样的内容:
Array
(
[0] => ./1.png
[1] => ./a.php
[2] => ./adminer
[3] => ./adminer/adminer.css
[4] => ./adminer/adminer.php
)
有什么办法可以得到 RecursiveDirectoryIterator
/FilesystemIterator
模拟 glob()
中存在的 GLOB_MARK
行为功能?来自手册:
GLOB_MARK - Adds a slash to each directory returned.
我知道我可以通过简单地执行以下操作来模仿:
foreach ($files as $key => $value)
{
$files[$key] .= (is_dir($value) ? '/' : '');
}
但这需要(不必要的?)多次访问磁盘。我正在寻找一种方法来快速确定路径是目录还是常规文件,结尾斜杠似乎是理想的解决方案。
我计划用它来遍历数十(如果不是数百)数千个文件,因此性能至关重要。
额外问题:有没有办法只获取目录(递归)?
最佳答案
您可以创建自己的GlobMarkIterator
优点:
- 将结束斜杠返回到目录,就像
GLOB_MARK
- 无需使用
array_map
和strval
将其转换为字符串 - 没有额外的
foreach
循环与is_dir
- 仍然和原来一样快
- 是的,我知道我作弊了
示例
$ri = new RecursiveIteratorIterator(new GlobMarkIterator('./', FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS), RecursiveIteratorIterator::SELF_FIRST);
$files = array_values(iterator_to_array($ri));
echo "<pre>";
print_r($files);
输出
Array
(
[0] => ./test/backups/ <----------- Note ending slash
[1] => ./test/CSV/
[2] => ./test/CSV/abc.csv
[3] => ./test/final/
[4] => ./test/thumb/
[5] => ./test/thumb/a.png
[6] => ./test/thumb/s.svg
[7] => ./test/thumb/sample.svg
)
额外问题:有没有办法只获取目录(递归)?
这应该是另一个问题,但都一样......我希望你不要满意并对此给予赏金
解决方案:
$ri = new RecursiveIteratorIterator( new GlobMarkDirectory('./test'), RecursiveIteratorIterator::SELF_FIRST);
$dir = array_values(iterator_to_array($ri));
echo "<pre>";
print_r($dir);
输出
Array
(
[0] => ./test/backups/
[1] => ./test/CSV/
[2] => ./test/final/
[3] => ./test/thumb/
)
使用的类
GlobMarkIterator
class GlobMarkIterator extends RecursiveDirectoryIterator {
function current() {
return $this->isDir() ? $this->getPathname() . "/" : $this->getPathname();
}
}
GlobMarkDirectory
类
class GlobMarkDirectory extends RecursiveFilterIterator {
public function __construct($path) {
parent::__construct(new GlobMarkIterator($path, FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS));
}
public function accept() {
return $this->getInnerIterator()->isDir();
}
public function getChildren() {
return new GlobMarkDirectory($this->getInnerIterator()->getPathname());
}
}
编辑..如果您不关心empty dir
并且由于速度和开销而不想使用isDir
,这里是另一个解决方案
解决方案
$ri = new RecursiveIteratorIterator(new GlobMarkFastDirectory (__DIR__), RecursiveIteratorIterator::SELF_FIRST);
$dir = array_values(array_unique(iterator_to_array($ri)));
GlobMarkFastDirectory
class GlobMarkFastDirectory extends RecursiveDirectoryIterator {
function current() {
return dirname($this->getPathname()) ."/";
}
}
关于php - 使用 FilesystemIterator 将尾部斜杠应用于文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12988204/