【问题标题】:How to recursively iterate through files in PHP?如何递归遍历PHP中的文件?
【发布时间】:2014-11-12 15:01:30
【问题描述】:

我已经设置了一个基本脚本,它发布一组路径以在其中查找模板文件;目前它只搜索两个级别的深度,我在理解一个广泛循环的逻辑以迭代所有子目录直到长度为 0 时遇到了一些麻烦。

如果我有这样的结构:

./components
./components/template.html
./components/template2.html
./components/side/template.html
./components/side/template2.html
./components/side/second/template.html
./components/side/second/template2.html
./components/side/second/third/template.html
./components/side/second/third/template2.html

当理想情况下我希望它检查所有子目录和传递的 .html 文件目录时,它只会在“side”目录中搜索 .html 文件。到目前为止,这是我的工作代码:

<?php
function getFiles($path){
    $dh  = opendir($path);
    foreach(glob($path.'/*.html') as $filename){
        $files[] = $filename;
    }
    if (isset($files)) {
        return $files;
    }
}
foreach ($_POST as $path) {
    foreach (glob($path . '/*' , GLOB_ONLYDIR) as $secondLevel) {
        $files[] = getFiles($secondLevel);
    }
    $files[] = getFiles($path);
}
sort($files);
print_r(json_encode($files));
?>

【问题讨论】:

标签: php loops


【解决方案1】:

PHP 内置了完美的解决方案。

示例

// Construct the iterator
$it = new RecursiveDirectoryIterator("/components");

// Loop through files
foreach(new RecursiveIteratorIterator($it) as $file) {
    if ($file->getExtension() == 'html') {
        echo $file;
    }
}

资源

【讨论】:

  • 谢谢,这看起来正是我想要的。
【解决方案2】:

PHP 5 引入了迭代器以快速迭代许多元素。

您可以使用RecursiveDirectoryIterator 递归地遍历目录。

您可以在结果上使用RecursiveIteratorIterator 以获得结果的平面视图。

您可以在结果上使用RegexIterator,根据正则表达式进行过滤。

 $directory_iterator = new RecursiveDirectoryIterator('.');
 $iterator       = new RecursiveIteratorIterator($directory_iterator);
 $regex_iterator = new RegexIterator($iterator, '/\.php$/');
 $regex_iterator->setFlags(RegexIterator::USE_KEY);
 foreach ($regex_iterator as $file) {
    echo $file->getPathname() . PHP_EOL;
 }

使用迭代器,有很多方法可以做同样的事情,您也可以使用FilterIterator(参见页面上的示例)

例如,如果要选择本周修改过的文件,可以使用如下:

  $directory_iterator = new RecursiveDirectoryIterator('.');
  $iterator       = new RecursiveIteratorIterator($directory_iterator);

  class CustomFilterIterator extends FilterIterator {
       function accept() {
            $current=$this->getInnerIterator()->current();
            return ($current->isFile()&&$current->getMTime()>time()-3600*24*7);
       }
  }

  $filter_iterator=new CustomFilterIterator($iterator);
  foreach ($filter_iterator as $file) {
     echo $file->getPathname() . PHP_EOL;
  }

【讨论】:

    【解决方案3】:

    另一个解决方案是使用 Symfony 的 Finder 组件。它是经过测试和验证的代码。看看这里:http://symfony.com/doc/current/components/finder.html

    【讨论】:

      【解决方案4】:

      这是工作代码,它将给定目录 $dir 及其所有子目录扫描到任何级别,并返回包含它们的 html 文件和文件夹的列表。

      <?php
      
      function find_all_files($dir)
      {
      
          if(!is_dir($dir)) return false;
      
          $pathinfo = '';
      
      
          $root = scandir($dir);
      
          foreach($root as $value)
          {
              if($value === '.' || $value === '..') {continue;}
      
      
      
      
              if(is_file("$dir/$value")) {
      
                  $pathinfo = pathinfo($dir.'/'.$value);
      
                  if($pathinfo['extension'] == 'html') {
                      $result[]="$dir/$value";
      
      
                  }
      
                  continue;
      
              }
      
              foreach(find_all_files("$dir/$value") as $value)
              {
      
                  $result[]=$value;
      
              }
          }
      
          return $result;
      
      }
      
      //call function
      $res = find_all_files('physical path to folder'); 
      
      print_r($res);
      
      ?>
      

      【讨论】:

        【解决方案5】:

        文件夹、子文件夹中的通用文件搜索:

        function dirToArray($dir,$file_name) {
           $result = array();
           $cdir = scandir($dir);
           foreach ($cdir as $key => $value)
           {
              if (!in_array($value,array(".","..")))
              {
                 if (is_dir($dir . DIRECTORY_SEPARATOR . $value))
                 {
                    $result[$value] = dirToArray($dir . DIRECTORY_SEPARATOR . $value,$file_name);
                 }
                 else
                 {
                    if($value == $file_name){
                        $result[] = $value; 
                    }
                 }
              }
           }
           return $result;
        }
        
        define('ROOT', dirname(__FILE__));
        $file_name = 'template.html';
        $tree = dirToArray(ROOT,$file_name);
        echo "<pre>".print_r($tree,1)."</pre>";
        

        输出:

        Array
        (
            [components] => Array
                (
                    [side] => Array
                        (
                            [second] => Array
                                (
                                    [0] => template.html
                                    [third] => Array
                                        (
                                            [0] => template.html
                                        )
        
                                )
        
                            [0] => template.html
                        )
        
                    [0] => template.html
                )
        
            [0] => template.html
        )
        

        【讨论】:

          【解决方案6】:

          我之前的答案的替代方案:

          $dir = 'components';
          function getFiles($dir, &$results = array(), $filename = 'template.html'){
              $files = scandir($dir);
              foreach($files as $key => $value){
                  $path = realpath($dir.'/'.$value);
                  if(!is_dir($path)) {
                      if($value == $filename)         
                          $results[] = $path;         
                  } else if($value != "." && $value != "..") {
                      getFiles($path, $results);
                  }
              }
              return $results;
          }
          echo '<pre>'.print_r(getFiles($dir), 1).'</pre>';
          

          输出:

          Array
          (
              [0] => /web/practise/php/others/test7/components/side/second/template.html
              [1] => /web/practise/php/others/test7/components/side/second/third/template.html
              [2] => /web/practise/php/others/test7/components/side/template.html
              [3] => /web/practise/php/others/test7/components/template.html
          )
          

          【讨论】:

            【解决方案7】:

            这是一个通用的解决方案:

            function parseDir($dir, &$files=array(), $extension=false){
            
            if(!is_dir($dir)){
                $info =  pathinfo($dir);
                // add all files if extension is set to false
                if($extension === false || (isset($info['extension']) && $info['extension'] === $extension)){
                    $files[] = $dir;
                }
            }else{
                if(substr($dir, -1) !== '.' && $dh =  opendir($dir)){
                    while($file = readdir($dh)){
                        parseDir("$dir/$file", $files, $extension);
                    }
                }
            }
             }
            
            $files = array();
            parseDir('components', $files, 'html');
            var_dump($files);
            

            输出

            php parseDir.php 
            array(7) {
              [0]=>
              string(25) "components/template2.html"
              [1]=>
              string(29) "components/side/template.html"
              [2]=>
              string(30) "components/side/template2.html"
              [3]=>
              string(36) "components/side/second/template.html"
              [4]=>
              string(37) "components/side/second/template2.html"
              [5]=>
              string(42) "components/side/second/third/template.html"
              [6]=>
              string(43) "components/side/second/third/template2.html"
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-03-12
              • 1970-01-01
              • 2011-03-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-07-24
              • 1970-01-01
              相关资源
              最近更新 更多