【问题标题】:Recursive directory to array in PHP; relative mapped to absolute递归目录到 PHP 中的数组;相对映射到绝对
【发布时间】:2011-11-15 16:06:26
【问题描述】:

我正在将递归目录列表中的结果提取到一个数组中,并且想知道是否有更好的(阅读速度更快、更简洁,等等)方法。具体来说,我正在创建一个数组:

path_relative_to_somedir => absolute_path

现在我有:

$map = array();
$base_realpath = realpath('/path/to/dir');
$iterator = new \RecursiveDirectoryIterator($base_realpath);
foreach((new \RecursiveIteratorIterator($iterator)) as $node){
    $node_realpath = $node->getRealpath();
    $map[substr($node_realpath, strlen($base_realpath) + 1)] = $node_realpath;
}

这很好用(似乎),但我担心边缘情况,虽然我确信它们会在测试中出现,但其他人可能会指出。所以:

  • 是否有更好的(读取速度更快、更准确、更可靠)方法来获取相对于$base_realpath 的节点路径?
  • 我是否应该考虑将glob()readdir() 等选项作为更快 的替代方案? (这是一个有点时间敏感的操作,我看到一个与 PHP 中的目录递归有关的问题,答案中有一些基准,找到时会链接

--问题结束--


--可能是不必要的细节开始--

目的;我正在为应用程序创建一个虚拟工作目录,以便对给定文件的调用映射到实际文件。例如:(我正在详细说明,以防有人根据我实际在做的事情有一个整体更好的替代方法

鉴于dir1 是虚拟工作目录的“根”,我们希望合并到dir2

path/                       path/
|                           |
+-- to/                     +-- to/
    |                           |
    +-- dir1/                   +-- dir2/
        |                           |
        +-- script1.php             +-- script2.php
        |                           |
        +-- script2.php             +-- subdir/
        |                               | 
        +-- subdir/                     +-- script4.php
            |               
            +-- script3.php 

它会产生一个像这样的数组:

[script1.php] => path/to/dir1/script1.php
[script2.php] => path/to/dir2/script2.php
[subdir/script3.php] => path/to/dir1/subdir/script3.php
[subdir/script4.php] => path/to/dir2/subdir/script4.php

请注意,合并替换了现有的相对路径,并且每个元素都映射到它的实际路径。我这里只是用array_replace(),这里是sn-p的方法:

public function mergeModule($name){
    $path = realpath($this->_application->getPath() . 'modules/' . $name);
    if(!is_dir($path) || !is_readable($path)){
        // @todo; throw exception
    }
    $map = array();
    try{
        $directory_iterator = new \RecursiveDirectoryIterator($path);
        foreach((new \RecursiveIteratorIterator($directory_iterator)) as $node){
            $node_realpath = $node->getRealpath();
            $map[substr($node_realpath, strlen($path) + 1)] = $node_realpath;
        }
    }catch(\Exception $exception){
        // @todo; handle
    }
    $this->_map = array_replace($this->_map, $map);
}

【问题讨论】:

  • 您的示例在“to”目录中有 script2.php,而不是与您产生的输出冲突的“dir2”目录。你能解决这个问题吗?
  • 哎呀,谢谢@hafichuk - 修复。
  • 这几乎不值得一提,但请记住 PHP 不容易优化,因此值得在循环外缓存 strlen($base_realpath) + 1 之类的值。我假设strlen 是一个简单的O(1) 操作,但如果你做了很多,即使是函数调用也会累加。
  • @Matthew - 确实如此;我实际上在 SO 编辑框中重新键入了该功能,我通常会采取这种预防措施。实际上,我想知道获取给定资源的相对路径的最佳方法是什么(slice path/to/dir from path/to/dir/subdir1/file2.php - 我可以使用字符串长度,还是应该做一些更直观的事情? i>)
  • @Bracketworks,简而言之,我认为您收集文件列表的方式没有什么特别的问题。这与我将使用的技术相同,包括使用substr 来获取相对路径。如果您担心速度,那就尝试一下并做一些基准测试,但无论您选择使用哪种 API,底层 I/O 都应该是瓶颈。

标签: php path directory-structure


【解决方案1】:

如果您正在寻找一种更快的递归方式列出目录的方法,您可以尝试使用外部程序。快很多:)

exec('tree -if /var/www',$tree);
foreach($tree as $key => $path) {
    if ( !$path ) // Ignore the summary ex "5 directories, 30 files"
       break;

    // Do something with the file/dir path
}

如果您只需要 .php 文件,您可以使用 find 命令。

find . -name "*.php"

【讨论】:

  • tree 在大多数 UNIX 系统上默认不可用。 find 是(您可以省略 -name "*.php" 以匹配所有文件),但它不太可能特别快。
猜你喜欢
  • 2016-11-02
  • 2011-02-14
  • 2011-06-14
  • 2017-10-11
  • 1970-01-01
  • 2022-11-24
  • 1970-01-01
  • 2021-04-18
  • 2015-10-02
相关资源
最近更新 更多