【问题标题】:Listing all the folders subfolders and files in a directory using php使用php列出目录中的所有文件夹子文件夹和文件
【发布时间】:2011-10-30 14:12:31
【问题描述】:

请给我一个使用php列出目录中所有文件夹、子文件夹、文件的解决方案。我的文件夹结构是这样的:

Main Dir
 Dir1
  SubDir1
   File1
   File2
  SubDir2
   File3
   File4
 Dir2
  SubDir3
   File5
   File6
  SubDir4
   File7
   File8

我想获取每个文件夹中所有文件的列表。

php中有shell脚本命令吗?

【问题讨论】:

    标签: php directory


    【解决方案1】:

    【讨论】:

      【解决方案2】:
      【解决方案3】:

      我真的很喜欢 SPL 库,他们提供迭代器,包括 RecursiveDirectoryIterator

      【讨论】:

        【解决方案4】:
        function listFolderFiles($dir){
            $ffs = scandir($dir);
        
            unset($ffs[array_search('.', $ffs, true)]);
            unset($ffs[array_search('..', $ffs, true)]);
        
            // prevent empty ordered elements
            if (count($ffs) < 1)
                return;
        
            echo '<ol>';
            foreach($ffs as $ff){
                echo '<li>'.$ff;
                if(is_dir($dir.'/'.$ff)) listFolderFiles($dir.'/'.$ff);
                echo '</li>';
            }
            echo '</ol>';
        }
        
        listFolderFiles('Main Dir');
        

        【讨论】:

        • 谢谢Shef,它工作正常他们有任何shell命令来执行这个吗?
        • 不问你是否有任何单一的 shell 脚本来列出所有文件夹和文件,如 esec(find)
        • @THOmas:据我所知没有。此外,exec 不允许在任何地方使用,因此运行它会遇到问题。
        • 函数列表文件夹($dir=null){ $ffs = scandir( WWW_ROOT."upload" );我像这样使用它,它在获取父文件夹项目后停止..请帮助@shef
        • @MonteCristo 你有函数,$ff 循环内的变量foreach 保存文件名。使用filesize($ff)filemtime($ff)filetype($ff)等各自的函数来实现你想要的。
        【解决方案5】:

        你也可以试试这个:

        <?php
        function listdirs($dir) {
            static $alldirs = array();
            $dirs = glob($dir . '/*', GLOB_ONLYDIR);
            if (count($dirs) > 0) {
                foreach ($dirs as $d) $alldirs[] = $d;
            }
            foreach ($dirs as $dir) listdirs($dir);
            return $alldirs;
        }
        
        $directory_list = listdirs('xampp');
        print_r($directory_list);
        ?>
        

        【讨论】:

          【解决方案6】:
          define ('PATH', $_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['PHP_SELF']));
          $dir = new DirectoryIterator(PATH);
          echo '<ul>';
          foreach ($dir as $fileinfo)
          {   
              if (!$fileinfo->isDot()) {
                 echo '<li><a href="'.$fileinfo->getFilename().'" target="_blank">'.$fileinfo->getFilename().'</a></li>'; 
          
                 echo '</li>';
              }
          }
          echo '</ul>';
          

          【讨论】:

            【解决方案7】:

            此代码在树视图中按排序顺序列出所有目录和文件。它是一个站点地图生成器,带有指向所有站点资源的超链接。完整的网页源代码在这里。您需要更改从末尾算起的第 9 行的路径。

            <?php
            $pathLen = 0;
            
            function prePad($level)
            {
              $ss = "";
            
              for ($ii = 0;  $ii < $level;  $ii++)
              {
                $ss = $ss . "|&nbsp;&nbsp;";
              }
            
              return $ss;
            }
            
            function myScanDir($dir, $level, $rootLen)
            {
              global $pathLen;
            
              if ($handle = opendir($dir)) {
            
                $allFiles = array();
            
                while (false !== ($entry = readdir($handle))) {
                  if ($entry != "." && $entry != "..") {
                    if (is_dir($dir . "/" . $entry))
                    {
                      $allFiles[] = "D: " . $dir . "/" . $entry;
                    }
                    else
                    {
                      $allFiles[] = "F: " . $dir . "/" . $entry;
                    }
                  }
                }
                closedir($handle);
            
                natsort($allFiles);
            
                foreach($allFiles as $value)
                {
                  $displayName = substr($value, $rootLen + 4);
                  $fileName    = substr($value, 3);
                  $linkName    = str_replace(" ", "%20", substr($value, $pathLen + 3));
                  if (is_dir($fileName)) {
                    echo prePad($level) . $linkName . "<br>\n";
                    myScanDir($fileName, $level + 1, strlen($fileName));
                  } else {
                    echo prePad($level) . "<a href=\"" . $linkName . "\" style=\"text-decoration:none;\">" . $displayName . "</a><br>\n";
                  }
                }
              }
            }
            
            ?><!DOCTYPE HTML>
            <html lang="en">
            <head>
              <meta charset="UTF-8">
              <title>Site Map</title>
            </head>
            
            <body>
            <h1>Site Map</h1>
            <p style="font-family:'Courier New', Courier, monospace; font-size:small;">
            <?php
              $root = '/home/someuser/www/website.com/public';
            
              $pathLen = strlen($root);
            
              myScanDir($root, 0, strlen($root)); ?>
            </p>
            </body>
            
            </html>
            

            【讨论】:

            • 很好的解决方案,是不是可以简单的变漂亮一点?
            【解决方案8】:

            如果你想使用directoryIterator

            以下函数是@Shef 回答directoryIterator的重新实现

            function listFolderFiles($dir)
            {
                echo '<ol>';
                foreach (new DirectoryIterator($dir) as $fileInfo) {
                    if (!$fileInfo->isDot()) {
                        echo '<li>' . $fileInfo->getFilename();
                        if ($fileInfo->isDir()) {
                            listFolderFiles($fileInfo->getPathname());
                        }
                        echo '</li>';
                    }
                }
                echo '</ol>';
            }
            listFolderFiles('Main Dir');
            

            【讨论】:

            • 这很好用 echo $fileInfo->getPathname() .'\\' 删除一些 HTML 替换。 $fileInfo->getFilename() 。 "\n";你得到了所有文件,你可以做任何你需要的事情
            【解决方案9】:

            显示文件夹结构的一种非常简单的方法是使用RecursiveTreeIterator 类(PHP 5 >= 5.3.0,PHP 7)并生成一个 ASCII 图形树。

            $it = new RecursiveTreeIterator(new RecursiveDirectoryIterator("/path/to/dir", RecursiveDirectoryIterator::SKIP_DOTS));
            foreach($it as $path) {
              echo $path."<br>";
            }
            

            http://php.net/manual/en/class.recursivetreeiterator.php

            还可以通过使用RecursiveTreeIterator::setPrefixPart 更改前缀来控制树的ASCII 表示,例如$it-&gt;setPrefixPart(RecursiveTreeIterator::PREFIX_LEFT, "|");

            【讨论】:

            • 正是我需要的,我改为 $dir, RecursiveDirectoryIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS) 来获得斜线。却想不出如何避免 | | | |- 没有 str_replace
            • @Reign.85 我也没有设法避免这些字符。我不确定班级是否提供了一种方式...
            【解决方案10】:

            演出迟到了,但要建立在accepted answer...

            如果您想将所有文件和目录作为数组保存(可以在 javascript 中使用 JSON.stringify 很好地修饰),您可以将函数修改为:

            function listFolderFiles($dir) { 
                $arr = array();
                $ffs = scandir($dir);
            
                foreach($ffs as $ff) {
                    if($ff != '.' && $ff != '..') {
                        $arr[$ff] = array();
                        if(is_dir($dir.'/'.$ff)) {
                            $arr[$ff] = listFolderFiles($dir.'/'.$ff);
                        }
                    }
                }
            
                return $arr;
            }
            

            对于新手...

            要使用前面提到的JSON.stringify,你的 JS/jQuery 应该是这样的:

            var ajax = $.ajax({
                method: 'POST',
                data: {list_dirs: true}
            }).done(function(msg) {
                $('pre').html(
                    'FILE LAYOUT<br/>' + 
                        JSON.stringify(JSON.parse(msg), null, 4)
                );
            });
            

            ^ 这是假设您的 HTML 中某处有一个 &lt;pre&gt; 元素。任何风格的 AJAX 都可以,但我认为大多数人都在使用类似于上面的 jQuery 的东西。

            以及随附的 PHP:

            if(isset($_POST['list_dirs'])) {
                echo json_encode(listFolderFiles($rootPath));
                exit();
            }
            

            您之前已经拥有listFolderFiles

            就我而言,我已将$rootPath 设置为站点的根目录...

            $rootPath; 
            if(!isset($rootPath)) {
                $rootPath = $_SERVER['DOCUMENT_ROOT'];
            }
            

            最终的结果是……

            |    some_file_1487.smthng    []
            |    some_file_8752.smthng    []
            |    CSS    
            |    |    some_file_3615.smthng    []
            |    |    some_file_8151.smthng    []
            |    |    some_file_7571.smthng    []
            |    |    some_file_5641.smthng    []
            |    |    some_file_7305.smthng    []
            |    |    some_file_9527.smthng    []
            |    
            |    IMAGES    
            |    |    some_file_4515.smthng    []
            |    |    some_file_1335.smthng    []
            |    |    some_file_1819.smthng    []
            |    |    some_file_9188.smthng    []
            |    |    some_file_4760.smthng    []
            |    |    some_file_7347.smthng    []
            |    
            |    JSScripts    
            |    |    some_file_6449.smthng    []
            |    |    some_file_7864.smthng    []
            |    |    some_file_3899.smthng    []
            |    |    google-code-prettify    
            |    |    |    some_file_2090.smthng    []
            |    |    |    some_file_5169.smthng    []
            |    |    |    some_file_3426.smthng    []
            |    |    |    some_file_8208.smthng    []
            |    |    |    some_file_7581.smthng    []
            |    |    |    some_file_4618.smthng    []
            |    |    
            |    |    some_file_3883.smthng    []
            |    |    some_file_3713.smthng    []
            
            ... and so on...
            

            注意:您的不会完全像这样 - 我已修改 JSON.stringify 以显示选项卡(垂直管道)、对齐所有键值、删除键的引号以及其他一些事情。如果我要上传它,或者获得足够的兴趣,我会用一个链接修改这个答案。

            【讨论】:

              【解决方案11】:

              用于制作目录格式的菜单栏

              $pathLen = 0;
              
              function prePad($level)
              {
                $ss = "";
              
                for ($ii = 0;  $ii < $level;  $ii++)
                {
                    $ss = $ss . "|&nbsp;&nbsp;";
                  }
              
                  return $ss;
                }
              
                function myScanDir($dir, $level, $rootLen)
                {
                  global $pathLen;
              
                  if ($handle = opendir($dir)) {
              
                    $allFiles = array();
              
                    while (false !== ($entry = readdir($handle))) {
                      if ($entry != "." && $entry != "..") {
                        if (is_dir($dir . "/" . $entry))
                        {
                          $allFiles[] = "D: " . $dir . "/" . $entry;
                        }
                        else
                        {
                          $allFiles[] = "F: " . $dir . "/" . $entry;
                        }
                      }
                    }
                    closedir($handle);
              
                    natsort($allFiles);
              
                    foreach($allFiles as $value)
                    {
                      $displayName = substr($value, $rootLen + 4);
                      $fileName    = substr($value, 3);
                      $linkName    = str_replace(" ", " ", substr($value, $pathLen + 3));
              
              
                      if (is_dir($fileName))
                       {
                             echo "<li ><a class='dropdown'><span>" . $displayName . "                    </span></a><ul>";
              
                        myScanDir($fileName, $level + 1, strlen($fileName));
                          echo "</ul></li>";
                } 
                      else {
                    $newstring = substr($displayName, -3);  
                    if($newstring == "PDF" || $newstring == "pdf" )
              
                        echo "<li ><a href=\"" . $linkName . "\" style=\"text-decoration:none;\">" . $displayName . "</a></li>";
              
                      }
                $t;
                      if($level != 0)
                      {
                        if($level < $t)
                        {
                      $r = int($t) - int($level);
                      for($i=0;$i<$r;$i++)
                      {
                          echo "</ul></li>";
                      }
                        } 
                      }
                            $t = $level;
                    }
                        }
              
                      }
                      ?>
              
                                                      <li style="color: #ffffff">
              
                                                              <?php                                                   
                 //  ListFolder('D:\PDF');
                   $root = 'D:\PDF';
                 $pathLen = strlen($root);
              
                  myScanDir($root, 0, strlen($root)); 
                   ?>
              
              
                                                      </li>
              

              【讨论】:

                【解决方案12】:
                function GetDir($dir) {
                    if (is_dir($dir)) {
                        if ($kami = opendir($dir)) {
                            while ($file = readdir($kami)) {
                                if ($file != '.' && $file != '..') {
                                    if (is_dir($dir . $file)) {
                                        echo $dir . $file;
                                        // since it is a directory we recurse it.
                                        GetDir($dir . $file . '/');
                                    } else {
                                        echo $dir . $file;
                                    }
                                }
                            }
                        }
                        closedir($kami);
                    }
                }
                

                【讨论】:

                  【解决方案13】:

                  如果您正在寻找递归目录列出解决方案并将它们排列在多维数组中。使用以下代码:

                  <?php
                  /**
                   * Function for recursive directory file list search as an array.
                   *
                   * @param mixed $dir Main Directory Path.
                   *
                   * @return array
                   */
                  function listFolderFiles($dir)
                  {
                      $fileInfo     = scandir($dir);
                      $allFileLists = [];
                  
                      foreach ($fileInfo as $folder) {
                          if ($folder !== '.' && $folder !== '..') {
                              if (is_dir($dir . DIRECTORY_SEPARATOR . $folder) === true) {
                                  $allFileLists[$folder] = listFolderFiles($dir . DIRECTORY_SEPARATOR . $folder);
                              } else {
                                  $allFileLists[$folder] = $folder;
                              }
                          }
                      }
                  
                      return $allFileLists;
                  }//end listFolderFiles()
                  
                  
                  $dir = listFolderFiles('your searching directory path ex:-F:\xampp\htdocs\abc');
                  echo '<pre>';
                  print_r($dir);
                  echo '</pre>'
                  
                  ?>
                  

                  【讨论】:

                    【解决方案14】:

                    这是一个简单的函数,带有 scandir& array_filter 可以完成这项工作。筛选 使用正则表达式所需的文件。我删除了. ...htaccess 之类的隐藏文件,您还可以使用&lt;ul&gt; 和颜色自定义输出,还可以自定义错误以防没有扫描或空目录!

                    function getAllContentOfLocation($loc)
                    {   
                        $scandir = scandir($loc);
                    
                        $scandir = array_filter($scandir, function($element){
                    
                            return !preg_match('/^\./', $element);
                    
                        });
                    
                        if(empty($scandir)) echo '<li style="color:red">Empty Dir</li>';
                    
                        foreach($scandir as $file){
                    
                            $baseLink = $loc . DIRECTORY_SEPARATOR . $file;
                    
                            echo '<ol>';
                            if(is_dir($baseLink))
                            {
                                echo '<li style="font-weight:bold;color:blue">'.$file.'</li>';
                                getAllContentOfLocation($baseLink);
                    
                            }else{
                                echo '<li>'.$file.'</li>';
                            }
                            echo '</ol>';
                        }
                    }
                    //Call function and set location that you want to scan 
                    getAllContentOfLocation('../app');
                    

                    【讨论】:

                      【解决方案15】:

                      我一直在寻找与此类似的功能。我需要将目录作为键,将子目录作为数组和文件作为值放置。
                      我使用了以下代码:

                      /**
                       * Return an array of files found within a specified directory.
                       * @param  string $dir   A valid directory. If a path, with a file at the end,
                       *                       is passed, then the file is trimmed from the directory.
                       * @param  string $regex Optional. If passed, all file names will be checked
                       *                       against the expression, and only those that match will
                       *                       be returned.
                       *                       A RegEx can be just a string, where a '/' will be
                       *                       prefixed and a '/i' will be suffixed. Alternatively,
                       *                       a string could be a valid RegEx string.
                       * @return array         An array of all files from that directory. If regex is
                       *                       set, then this will be an array of any matching files.
                       */
                      function get_files_in_dir(string $dir, $regex = null)
                      {
                          $dir = is_dir($dir) ? $dir : dirname($dir);
                          // A RegEx to check whether a RegEx is a valid RegEx :D
                          $pass = preg_match("/^([^\\\\a-z ]).+([^\\\\a-z ])[a-z]*$/i", $regex, $matches);
                      
                          // Any non-regex string will be caught here.
                          if (isset($regex) && !$pass) {
                              //$regex = '/'.addslashes($regex).'/i';
                              $regex = "/$regex/i";
                          }
                      
                          // A valid regex delimiter with different delimiters will be caught here.
                          if (!empty($matches) && $matches[1] !== $matches[2]) {
                              $regex .= $matches[1] . 'i'; // Append first delimiter and i flag
                          }
                      
                          try {
                              $files = scandir($dir);
                          } catch (Exception $ex) {
                              $files = ['.', '..'];
                          }
                          $files = array_slice($files, 2); // Remove '.' and '..'
                          $files = array_reduce($files, function($carry, $item) use ($regex) {
                              if ((!empty($regex) && preg_match($regex, $item)) || empty($regex)) {
                                  array_push($carry, $item);
                              }
                      
                              return $carry;
                          }, []);
                      
                          return $files;
                      }
                      
                      function str_finish($value, $cap)
                      {
                          $quoted = preg_quote($cap, '/');
                      
                          return preg_replace('/(?:'.$quoted.')+$/u', '', $value).$cap;
                      }
                      
                      function get_directory_tree($dir)
                      {
                          $fs = get_files_in_dir($dir);
                          $files = array();
                      
                          foreach ($fs as $k => $f) {
                              if (is_dir(str_finish($dir, '/').$f)) {
                                  $fs[$f] = get_directory_tree(str_finish($dir, '/').$f);
                              } else {
                                  $files[] = $f;
                              }
                              unset($fs[$k]);
                      
                          }
                      
                          $fs = array_merge($fs, $files);
                      
                          return $fs;
                      }
                      

                      有很多东西可以吸收。

                      创建了第一个函数get_files_in_dir 函数,以便我可以根据正则表达式获取目录中的所有文件和文件夹。我在这里使用它是因为它有一些错误检查以确保将目录转换为数组。

                      接下来,我们有一个简单的函数,如果字符串末尾还没有正斜杠,它只需在字符串末尾添加一个正斜杠。

                      最后,我们有 get_directory_tree 函数,它将遍历所有文件夹和子文件夹并创建一个关联数组,其中文件夹名称是键,文件是值(除非文件夹有子文件夹)。

                      【讨论】:

                        【解决方案16】:

                        这篇文章是给 Shef(发布正确答案的人)的。这是我能想到向他展示我多么欣赏他的代码以及我用它做了什么的唯一方法。

                        <!DOCTYPE html>
                        <head><title>Displays Folder Contents</title></head>
                        <?php
                        
                        function frmtFolder($Entity){
                         echo '<li style="font-weight:bold;color:black;list-style-type:none">' . $Entity;
                        }
                        
                        function frmtFile($dEntry, $fEntry){
                        echo '<li style="list-style-type:square">' . '<a href="' . $dEntry . '/' . $fEntry . 
                        '"> ' . $fEntry . ' </a>';
                        }
                        
                        function listFolderFiles($dir) {
                        $ffs = scandir($dir);
                        
                        unset($ffs[array_search('.', $ffs, true)]);
                        unset($ffs[array_search('..', $ffs, true)]);
                        unset($ffs[array_search('index.html', $ffs, true)]);
                        // prevent empty ordered elements
                        if (count($ffs) < 1) {return;}
                        echo '<ul>';
                        foreach ($ffs as $ff) {
                            if (is_dir($dir . '/' . $ff)) {
                             frmtFolder($dir);
                            } else {
                             frmtFile($dir, $ff);
                            }
                            if (is_dir($dir . '/' . $ff)) {
                                listFolderFiles($dir . '/' . $ff);
                            }
                            echo '</li>';
                        }
                        echo '</ul>';
                        }
                        listFolderFiles('Folder_To_List_Here');
                        

                        我计划将来扩展 frmtFile 以使用音频和视频标签。

                        【讨论】:

                          【解决方案17】:

                          先例的答案不符合我的需求。

                          如果您希望将所有文件和目录放在一个平面数组中,您可以使用此功能(找到 here):

                          // Does not support flag GLOB_BRACE        
                          function glob_recursive($pattern, $flags = 0) {
                              $files = glob($pattern, $flags);
                              foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
                                  $files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags));
                              }
                              return $files;
                          }
                          

                          就我而言:

                          $paths = glob_recursive(os_path_join($base_path, $current_directory, "*"));
                          

                          返回一个这样的数组:

                          [
                          '/home/dir',
                          '/home/dir/image.png',
                          '/home/dir/subdir',
                          '/home/dir/subdir/file.php',
                          ]
                          

                          你也可以使用动态路径生成:

                          $paths = glob_recursive(os_path_join($base_path, $directory, "*"));
                          

                          有了这个功能:

                          function os_path_join(...$parts) {
                            return preg_replace('#'.DIRECTORY_SEPARATOR.'+#', DIRECTORY_SEPARATOR, implode(DIRECTORY_SEPARATOR, array_filter($parts)));
                          }
                          

                          如果您只想获取可以使用的目录:

                          $paths = glob_recursive(os_path_join($base_path, $current_directory, "*"));
                          $subdirs = array_filter($paths, function($path) {
                              return is_dir($path);
                          });
                          

                          【讨论】:

                            【解决方案18】:

                            https://3v4l.org/VsQLb 此处示例

                            function listdirs($dir) {
                                static $alldirs = array();
                                $dirs = glob($dir . '/*', GLOB_ONLYDIR);
                                if (count($dirs) > 0) {
                                    foreach ($dirs as $d) $alldirs[] = $d;
                                }
                                foreach ($dirs as $dir) listdirs($dir);
                                return $alldirs;
                            }
                            

                            【讨论】:

                              【解决方案19】:

                              这是我的 PHP 7 风格的方便方法:

                                /**
                                   * @param string $directory
                                   *
                                   * @return SplFileInfo[]
                                   */
                                  private function getAllFiles(string $directory = './'): array
                                  {
                                      $result = [];
                              
                                      $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory), RecursiveIteratorIterator::SELF_FIRST );
                                      /** @var $fileInfo SplFileInfo */
                                      foreach ($iterator as $fileInfo ) {
                              
                                          if ($fileInfo->isFile()) {
                                             $result[] = $fileInfo;
                                          }
                                      }
                              
                                      return $result;
                                  }
                              

                              【讨论】:

                                【解决方案20】:

                                这是另一个递归 scandir() 作为生成器。生成器生成完整路径(以"basedir/subdirs.../file" 的形式),因此它不太适合树形显示,而更适合您想要对文件路径执行其他操作的目录扫描 - 例如显示图片库。

                                function listFolderFiles($dir){
                                    foreach(scandir($dir) as $file){
                                        if ($file[0] == '.')
                                            continue;
                                        if (is_dir("$dir/$file"))
                                            foreach (listFolderFiles("$dir/$file") as $infile)
                                                yield $infile;
                                        else
                                            yield "${dir}/${file}";
                                    }
                                }
                                

                                此实现通过跳过所有 UNIX 隐藏文件(以句点开头的文件)来跳过目录指针 - 如果您想获取“隐藏”文件,那么您需要将目录指针跳过方法更改为其他方式。

                                你可以这样使用它:

                                <?php foreach (listFolderFiles('.') as $file) {
                                    ?>
                                    <?php echo $file?><br/>
                                    <?php
                                }?>
                                

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2020-07-02
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2016-11-11
                                  • 2011-05-11
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多