【问题标题】:List all the files and folders in a Directory with PHP recursive function使用 PHP 递归函数列出目录中的所有文件和文件夹
【发布时间】:2014-09-07 03:55:04
【问题描述】:

我正在尝试浏览目录中的所有文件,如果有目录,则浏览其所有文件,依此类推,直到没有更多目录可以访问。每个已处理的项目都将添加到下面函数中的结果数组中。虽然我不确定我能做什么/我做错了什么,但它不起作用,但是当处理下面的代码时,浏览器运行得非常慢,感谢任何帮助,谢谢!

代码:

    function getDirContents($dir){
        $results = array();
        $files = scandir($dir);

            foreach($files as $key => $value){
                if(!is_dir($dir. DIRECTORY_SEPARATOR .$value)){
                    $results[] = $value;
                } else if(is_dir($dir. DIRECTORY_SEPARATOR .$value)) {
                    $results[] = $value;
                    getDirContents($dir. DIRECTORY_SEPARATOR .$value);
                }
            }
    }

    print_r(getDirContents('/xampp/htdocs/WORK'));

【问题讨论】:

  • RecursiveDirectoryIterator
  • @user3412869 如果您有...,请不要调用函数。看我的回答。

标签: php recursion


【解决方案1】:

这是一个获取RecursiveIteratorIterator目录下所有文件和文件夹的函数。

请参阅建设者文档:https://www.php.net/manual/en/recursiveiteratoriterator.construct.php

function getDirContents($path) {
    $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));

    $files = array(); 
    foreach ($rii as $file)
        if (!$file->isDir())
            $files[] = $file->getPathname();

    return $files;
}

var_dump(getDirContents($path));

【讨论】:

  • Zkanoca 的版本很好,你的答案并不是真正需要的,对他的评论就足够了。这归结为编码风格。
【解决方案2】:

我发现了这个简单的代码: https://stackoverflow.com/a/24981012

 $Directory = new RecursiveDirectoryIterator($path);
 $Iterator = new RecursiveIteratorIterator($Directory);
 //Filter to get only PDF, JPEG, JPG, GIF, TIF files.
 $Regex = new RegexIterator($Iterator, '/^.+(.jpe?g|.gif|.png|.tif|.pdf)$/i', RecursiveRegexIterator::GET_MATCH);

    foreach($Regex as $val => $Regex){
       echo "$val\n<br>";
    }

【讨论】:

    【解决方案3】:

    如果您使用的是 Laravel,您可以使用 Storage 外观上的 getAllFiles 方法递归地获取所有文件,如下面的文档所示:https://laravel.com/docs/8.x/filesystem#get-all-files-within-a-directory

    use Illuminate\Support\Facades\Storage;
    
    class TestClass {
    
        public function test() {
            // Gets all the files in the 'storage/app' directory.
            $files = Storage::getAllFiles(storage_path('app'))
        }
    
    }
    
    

    【讨论】:

      【解决方案4】:

      为常见用例准备复制和粘贴功能,one answer above 的改进/扩展版本:

      function getDirContents(string $dir, int $onlyFiles = 0, string $excludeRegex = '~/\.git/~', int $maxDepth = -1): array {
          $results = [];
          $scanAll = scandir($dir);
          sort($scanAll);
          $scanDirs = []; $scanFiles = [];
          foreach($scanAll as $fName){
              if ($fName === '.' || $fName === '..') { continue; }
              $fPath = str_replace(DIRECTORY_SEPARATOR, '/', realpath($dir . '/' . $fName));
              if (strlen($excludeRegex) > 0 && preg_match($excludeRegex, $fPath . (is_dir($fPath) ? '/' : ''))) { continue; }
              if (is_dir($fPath)) {
                  $scanDirs[] = $fPath;
              } elseif ($onlyFiles >= 0) {
                  $scanFiles[] = $fPath;
              }
          }
      
          foreach ($scanDirs as $pDir) {
              if ($onlyFiles <= 0) {
                  $results[] = $pDir;
              }
              if ($maxDepth !== 0) {
                  foreach (getDirContents($pDir, $onlyFiles, $excludeRegex, $maxDepth - 1) as $p) {
                      $results[] = $p;
                  }
              }
          }
          foreach ($scanFiles as $p) {
              $results[] = $p;
          }
      
          return $results;
      }
      

      如果你需要相对路径:

      function updateKeysWithRelPath(array $paths, string $baseDir, bool $allowBaseDirPath = false): array {
          $results = [];
          $regex = '~^' . preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($baseDir)), '~') . '(?:/|$)~s';
          $regex = preg_replace('~/~', '/(?:(?!\.\.?/)(?:(?!/).)+/\.\.(?:/|$))?(?:\.(?:/|$))*', $regex); // limited to only one "/xx/../" expr
          if (DIRECTORY_SEPARATOR === '\\') {
              $regex = preg_replace('~/~', '[/\\\\\\\\]', $regex) . 'i';
          }
          foreach ($paths as $p) {
              $rel = preg_replace($regex, '', $p, 1);
              if ($rel === $p) {
                  throw new \Exception('Path relativize failed, path "' . $p . '" is not within basedir "' . $baseDir . '".');
              } elseif ($rel === '') {
                  if (!$allowBaseDirPath) {
                      throw new \Exception('Path relativize failed, basedir path "' . $p . '" not allowed.');
                  } else {
                      $results[$rel] = './';
                  }
              } else {
                  $results[$rel] = $p;
              }
          }
          return $results;
      }
      
      function getDirContentsWithRelKeys(string $dir, int $onlyFiles = 0, string $excludeRegex = '~/\.git/~', int $maxDepth = -1): array {
          return updateKeysWithRelPath(getDirContents($dir, $onlyFiles, $excludeRegex, $maxDepth), $dir);
      }
      

      此版本解决/改进:

      1. 当 PHP open_basedir 未覆盖 .. 目录时来自 realpath 的警告。
      2. 不使用结果数组的引用
      3. 允许排除目录和文件
      4. 只允许列出文件/目录
      5. 允许限制搜索深度
      6. 它总是首先按目录对输出进行排序(因此可以以相反的顺序删除/清空目录)
      7. 允许使用相对键获取路径
      8. 针对数十万甚至数百万个文件进行了大量优化
      9. 在 cmets 中写下更多内容 :)

      示例:

      // list only `*.php` files and skip .git/ and the current file
      $onlyPhpFilesExcludeRegex = '~/\.git/|(?<!/|\.php)$|^' . preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath(__FILE__)), '~') . '$~is';
      
      $phpFiles = getDirContents(__DIR__, 1, $onlyPhpFilesExcludeRegex);
      print_r($phpFiles);
      
      // with relative keys
      $phpFiles = getDirContentsWithRelKeys(__DIR__, 1, $onlyPhpFilesExcludeRegex);
      print_r($phpFiles);
      
      // with "include only" regex to include only .html and .txt files with "/*_mails/en/*.(html|txt)" path
      '~/\.git/|^(?!.*/(|' . '[^/]+_mails/en/[^/]+\.(?:html|txt)' . ')$)~is'
      

      【讨论】:

        【解决方案5】:

        获取一个目录下的所有文件和文件夹,当你有...时不要调用函数。

        你的代码:

        <?php
        function getDirContents($dir, &$results = array()) {
            $files = scandir($dir);
        
            foreach ($files as $key => $value) {
                $path = realpath($dir . DIRECTORY_SEPARATOR . $value);
                if (!is_dir($path)) {
                    $results[] = $path;
                } else if ($value != "." && $value != "..") {
                    getDirContents($path, $results);
                    $results[] = $path;
                }
            }
        
            return $results;
        }
        
        var_dump(getDirContents('/xampp/htdocs/WORK'));
        

        输出(示例):

        array (size=12)
          0 => string '/xampp/htdocs/WORK/iframe.html' (length=30)
          1 => string '/xampp/htdocs/WORK/index.html' (length=29)
          2 => string '/xampp/htdocs/WORK/js' (length=21)
          3 => string '/xampp/htdocs/WORK/js/btwn.js' (length=29)
          4 => string '/xampp/htdocs/WORK/js/qunit' (length=27)
          5 => string '/xampp/htdocs/WORK/js/qunit/qunit.css' (length=37)
          6 => string '/xampp/htdocs/WORK/js/qunit/qunit.js' (length=36)
          7 => string '/xampp/htdocs/WORK/js/unit-test.js' (length=34)
          8 => string '/xampp/htdocs/WORK/xxxxx.js' (length=30)
          9 => string '/xampp/htdocs/WORK/plane.png' (length=28)
          10 => string '/xampp/htdocs/WORK/qunit.html' (length=29)
          11 => string '/xampp/htdocs/WORK/styles.less' (length=30)
        

        【讨论】:

        • 是否有可能使结果数组中的每个文件夹都由其自己的数组保存所有子文件?
        • 将第 10 行替换为:getDirContents($path, $results[$path]);
        • 当性能至关重要时,使用scandir() 看起来不是一个好主意。更好的选择是RecursiveDirectoryIterator (php.net/manual/en/class.recursivedirectoryiterator.php)
        • 当目录为空时上面的函数返回总计数1
        • 使用realpath() 将给出同一目录中符号链接的目标名称。例如,在 linux 机器上尝试“/usr/lib64”上的示例。
        【解决方案6】:

        @A-312 的解决方案可能会导致内存问题,因为如果/xampp/htdocs/WORK 包含大量文件和文件夹,它可能会创建一个巨大的数组。

        如果您有 PHP 7,那么您可以使用 Generators 并像这样优化 PHP 的内存:

        function getDirContents($dir) {
            $files = scandir($dir);
            foreach($files as $key => $value){
        
                $path = realpath($dir.DIRECTORY_SEPARATOR.$value);
                if(!is_dir($path)) {
                    yield $path;
        
                } else if($value != "." && $value != "..") {
                   yield from getDirContents($path);
                   yield $path;
                }
            }
        }
        
        foreach(getDirContents('/xampp/htdocs/WORK') as $value) {
            echo $value."\n";
        }
        

        yield from

        【讨论】:

          【解决方案7】:

          添加相对路径选项:

          function getDirContents($dir, $relativePath = false)
          {
              $fileList = array();
              $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
              foreach ($iterator as $file) {
                  if ($file->isDir()) continue;
                  $path = $file->getPathname();
                  if ($relativePath) {
                      $path = str_replace($dir, '', $path);
                      $path = ltrim($path, '/\\');
                  }
                  $fileList[] = $path;
              }
              return $fileList;
          }
          
          print_r(getDirContents('/path/to/dir'));
          
          print_r(getDirContents('/path/to/dir', true));
          

          输出:

          Array
          (
              [0] => /path/to/dir/test1.html
              [1] => /path/to/dir/test.html
              [2] => /path/to/dir/index.php
          )
          
          Array
          (
              [0] => test1.html
              [1] => test.html
              [2] => index.php
          )
          

          【讨论】:

          • 这对我有用。我需要打包整个框架的文件然后列出。真正的选择带来了不同,而且小而整洁和高效。谢谢
          【解决方案8】:

          如果您希望以数组形式获取目录内容,忽略隐藏的文件和目录,这可能会有所帮助。

          function dir_tree($dir_path)
          {
              $rdi = new \RecursiveDirectoryIterator($dir_path);
          
              $rii = new \RecursiveIteratorIterator($rdi);
          
              $tree = [];
          
              foreach ($rii as $splFileInfo) {
                  $file_name = $splFileInfo->getFilename();
          
                  // Skip hidden files and directories.
                  if ($file_name[0] === '.') {
                      continue;
                  }
          
                  $path = $splFileInfo->isDir() ? array($file_name => array()) : array($file_name);
          
                  for ($depth = $rii->getDepth() - 1; $depth >= 0; $depth--) {
                      $path = array($rii->getSubIterator($depth)->current()->getFilename() => $path);
                  }
          
                  $tree = array_merge_recursive($tree, $path);
              }
          
              return $tree;
          }
          

          结果会是这样的;

          dir_tree(__DIR__.'/public');
          
          [
              'css' => [
                  'style.css',
                  'style.min.css',
              ],
              'js' => [
                  'script.js',
                  'script.min.js',
              ],
              'favicon.ico',
          ]
          

          Source

          【讨论】:

          • 感谢您的代码帮助我
          【解决方案9】:

          谁需要列表文件而不是文件夹(按字母顺序排列)。

          可以使用以下功能。 这不是自调用功能。所以你会有目录列表、目录视图、文件 列表和文件夹列表也作为单独的数组。

          我为此花了两天时间,也不希望有人为此浪费时间,希望对某人有所帮助。

          function dirlist($dir){
              if(!file_exists($dir)){ return $dir.' does not exists'; }
              $list = array('path' => $dir, 'dirview' => array(), 'dirlist' => array(), 'files' => array(), 'folders' => array());
          
              $dirs = array($dir);
              while(null !== ($dir = array_pop($dirs))){
                  if($dh = opendir($dir)){
                      while(false !== ($file = readdir($dh))){
                          if($file == '.' || $file == '..') continue;
                          $path = $dir.DIRECTORY_SEPARATOR.$file;
                          $list['dirlist_natural'][] = $path;
                          if(is_dir($path)){
                              $list['dirview'][$dir]['folders'][] = $path;
                              // Bos klasorler while icerisine tekrar girmeyecektir. Klasorun oldugundan emin olalım.
                              if(!isset($list['dirview'][$path])){ $list['dirview'][$path] = array(); }
                              $dirs[] = $path;
                              //if($path == 'D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-content\upgrade'){ press($path); press($list['dirview']); die; }
                          }
                          else{
                              $list['dirview'][$dir]['files'][] = $path;
                          }
                      }
                      closedir($dh);
                  }
              }
          
              // if(!empty($dirlist['dirlist_natural']))  sort($dirlist['dirlist_natural'], SORT_LOCALE_STRING); // delete safe ama gerek kalmadı.
          
              if(!empty($list['dirview'])) ksort($list['dirview']);
          
              // Dosyaları dogru sıralama yaptırıyoruz. Deniz P. - info[at]netinial.com
              foreach($list['dirview'] as $path => $file){
                  if(isset($file['files'])){
                      $list['dirlist'][] = $path;
                      $list['files'] = array_merge($list['files'], $file['files']);
                      $list['dirlist'] = array_merge($list['dirlist'], $file['files']);
                  }
                  // Add empty folders to the list
                  if(is_dir($path) && array_search($path, $list['dirlist']) === false){
                      $list['dirlist'][] = $path;
                  }
                  if(isset($file['folders'])){
                      $list['folders'] = array_merge($list['folders'], $file['folders']);
                  }
              }
          
              //press(array_diff($list['dirlist_natural'], $list['dirlist'])); press($list['dirview']); die;
          
              return $list;
          }
          

          会输出类似这样的内容。

          [D:\Xampp\htdocs\exclusiveyachtcharter.localhost] => Array
                          (
                              [files] => Array
                                  (
                                      [0] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\.htaccess
                                      [1] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\index.php
                                      [2] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\license.txt
                                      [3] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\php.php
                                      [4] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\readme.html
                                      [5] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-activate.php
                                      [6] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-blog-header.php
                                      [7] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-comments-post.php
                                      [8] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-config-sample.php
                                      [9] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-config.php
                                      [10] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-cron.php
                                      [11] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-links-opml.php
                                      [12] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-load.php
                                      [13] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-login.php
                                      [14] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-mail.php
                                      [15] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-settings.php
                                      [16] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-signup.php
                                      [17] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-trackback.php
                                      [18] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\xmlrpc.php
                                  )
          
                              [folders] => Array
                                  (
                                      [0] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\exclusiv_excluwlsql
                                      [1] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-admin
                                      [2] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-content
                                      [3] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-includes
                                  )
          
                          )
          

          目录输出

              [dirview] => Array
                  (
                      [0] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\.htaccess
                      [1] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\index.php
                      [2] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\license.txt
                      [3] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\php.php
                      [4] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\readme.html
                      [5] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-activate.php
                      [6] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-blog-header.php
                      [7] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-comments-post.php
                      [8] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-config-sample.php
                      [9] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-config.php
                      [10] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-cron.php
                      [11] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-links-opml.php
                      [12] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-load.php
                      [13] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-login.php
                      [14] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-mail.php
                      [15] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-settings.php
                      [16] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-signup.php
                      [17] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\wp-trackback.php
                      [18] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\xmlrpc.php
                      [19] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost
                      [20] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\exclusiv_excluwlsql\exclusiv_excluwl.sql
                      [21] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\exclusiv_excluwlsql\exclusiv_excluwl.sql.zip
                      [22] => D:\Xampp\htdocs\exclusiveyachtcharter.localhost\exclusiv_excluwlsql
          )
          

          【讨论】:

            【解决方案10】:

            这是 Hors 答案的修改版本,对我的情况稍微好一点,因为它去掉了传递的基本目录,并且有一个可以设置为 false 的递归开关,这也很方便。另外,为了使输出更具可读性,我将文件和子目录文件分开,因此先添加文件,然后添加子目录文件(我的意思见结果。)

            我尝试了其他一些方法和建议,这就是我最终的结果。我已经有另一种非常相似的工作方法,但是在没有文件的子目录但该子目录有一个子目录 with 文件的情况下似乎失败了,它没有扫描子目录中的文件 - 所以对于这种情况,可能需要测试一些答案。)...无论如何,我想我也会在这里发布我的版本,以防有人在寻找...

            function get_filelist_as_array($dir, $recursive = true, $basedir = '', $include_dirs = false) {
                if ($dir == '') {return array();} else {$results = array(); $subresults = array();}
                if (!is_dir($dir)) {$dir = dirname($dir);} // so a files path can be sent
                if ($basedir == '') {$basedir = realpath($dir).DIRECTORY_SEPARATOR;}
            
                $files = scandir($dir);
                foreach ($files as $key => $value){
                    if ( ($value != '.') && ($value != '..') ) {
                        $path = realpath($dir.DIRECTORY_SEPARATOR.$value);
                        if (is_dir($path)) {
                            // optionally include directories in file list
                            if ($include_dirs) {$subresults[] = str_replace($basedir, '', $path);}
                            // optionally get file list for all subdirectories
                            if ($recursive) {
                                $subdirresults = get_filelist_as_array($path, $recursive, $basedir, $include_dirs);
                                $results = array_merge($results, $subdirresults);
                            }
                        } else {
                            // strip basedir and add to subarray to separate file list
                            $subresults[] = str_replace($basedir, '', $path);
                        }
                    }
                }
                // merge the subarray to give the list of files then subdirectory files
                if (count($subresults) > 0) {$results = array_merge($subresults, $results);}
                return $results;
            }
            

            我想有一件事要小心,在调用它时不要将 $basedir 值传递给这个函数......主要只是传递 $dir (或者传递文件路径现在也可以)和可选的 $recursive 为 false如果需要的话。结果:

            [0] => demo-image.png
            [1] => filelist.php
            [2] => tile.png
            [3] => 2015\header.png
            [4] => 2015\08\background.jpg
            

            享受吧!好的,回到我实际使用的程序......

            更新添加了额外的参数,用于在文件列表中是否包含目录(记住需要传递其他参数才能使用它。)例如。

            $results = get_filelist_as_array($dir, true, '', true);

            【讨论】:

            • 谢谢,但此功能不列出目录。仅文件
            • @DenizPorsuk 好皮卡,当时肯定错过了这个问题。我添加了一个可选参数来包含目录或不包含目录。 :-)
            【解决方案11】:

            这是对majicks 答案的一点修改。
            我只是改变了函数返回的数组结构。

            发件人:

            array() => {
                [0] => "test/test.txt"
            }
            

            收件人:

            array() => {
                'test/test.txt' => "test.txt"
            }
            

            /**
             * @param string $dir
             * @param bool   $recursive
             * @param string $basedir
             *
             * @return array
             */
            function getFileListAsArray(string $dir, bool $recursive = true, string $basedir = ''): array {
                if ($dir == '') {
                    return array();
                } else {
                    $results = array();
                    $subresults = array();
                }
                if (!is_dir($dir)) {
                    $dir = dirname($dir);
                } // so a files path can be sent
                if ($basedir == '') {
                    $basedir = realpath($dir) . DIRECTORY_SEPARATOR;
                }
            
                $files = scandir($dir);
                foreach ($files as $key => $value) {
                    if (($value != '.') && ($value != '..')) {
                        $path = realpath($dir . DIRECTORY_SEPARATOR . $value);
                        if (is_dir($path)) { // do not combine with the next line or..
                            if ($recursive) { // ..non-recursive list will include subdirs
                                $subdirresults = self::getFileListAsArray($path, $recursive, $basedir);
                                $results = array_merge($results, $subdirresults);
                            }
                        } else { // strip basedir and add to subarray to separate file list
                            $subresults[str_replace($basedir, '', $path)] = $value;
                        }
                    }
                }
                // merge the subarray to give the list of files then subdirectory files
                if (count($subresults) > 0) {
                    $results = array_merge($subresults, $results);
                }
                return $results;
            }
            

            可能对像我一样具有完全相同预期结果的人有所帮助。

            【讨论】:

              【解决方案12】:
              $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('path/to/folder'));
              
              $files = array(); 
              
              foreach ($rii as $file) {
              
                  if ($file->isDir()){ 
                      continue;
                  }
              
                  $files[] = $file->getPathname(); 
              
              }
              
              
              
              var_dump($files);
              

              这将为您带来所有带有路径的文件。

              【讨论】:

              • 没有内置对象就没有办法做到这一点吗?
              • 或者您可以反转条件:if (!$file-&gt;isDir()) $files[] = $file-&gt;getPathname();。保存一行。
              • 也可以通过使用RecursiveDirectoryIterator::SKIP_DOTS来避免继续
              • 将 foreach 更改为:$Regex = new RegexIterator($rii, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH);
              • @RazvanGrigore 我不确定这对非 ... 目录有何帮助。你不需要过滤掉那些吗?
              【解决方案13】:

              使用过滤器(第二个参数)获取目录中的所有文件和文件夹,当你有...时不要调用函数。

              你的代码:

              <?php
              function getDirContents($dir, $filter = '', &$results = array()) {
                  $files = scandir($dir);
              
                  foreach($files as $key => $value){
                      $path = realpath($dir.DIRECTORY_SEPARATOR.$value); 
              
                      if(!is_dir($path)) {
                          if(empty($filter) || preg_match($filter, $path)) $results[] = $path;
                      } elseif($value != "." && $value != "..") {
                          getDirContents($path, $filter, $results);
                      }
                  }
              
                  return $results;
              } 
              
              // Simple Call: List all files
              var_dump(getDirContents('/xampp/htdocs/WORK'));
              
              // Regex Call: List php files only
              var_dump(getDirContents('/xampp/htdocs/WORK', '/\.php$/'));
              

              输出(示例):

              // Simple Call
              array(13) {
                [0]=> string(69) "/xampp/htdocs/WORK.htaccess"
                [1]=> string(73) "/xampp/htdocs/WORKConverter.php"
                [2]=> string(69) "/xampp/htdocs/WORKEvent.php"
                [3]=> string(70) "/xampp/htdocs/WORKdefault_filter.json"
                [4]=> string(68) "/xampp/htdocs/WORKdefault_filter.xml"
                [5]=> string(80) "/xampp/htdocs/WORKCaching/ApcCache.php"
                [6]=> string(84) "/xampp/htdocs/WORKCaching/CacheFactory.php"
              }
              
              // Regex Call
              array(13) {
                [0]=> string(69) "/xampp/htdocs/WORKEvent.php"
                [1]=> string(73) "/xampp/htdocs/WORKConverter.php"
                [2]=> string(80) "/xampp/htdocs/WORKCaching/ApcCache.php"
                [3]=> string(84) "/xampp/htdocs/WORKCaching/CacheFactory.php"
              }
              

              詹姆斯卡梅隆的提议。

              【讨论】:

                【解决方案14】:

                我的建议没有丑陋的“foreach”控制结构是

                $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
                $allFiles = array_filter(iterator_to_array($iterator), function($file) {
                    return $file->isFile();
                });
                

                您可能只想提取文件路径,您可以这样做:

                array_keys($allFiles);
                

                仍然是 4 行代码,但比使用循环或其他东西更直接。

                【讨论】:

                • 为了避免同时加载内存中的所有文件和目录,您还可以使用CallbackFilterIterator,以便稍后循环:$allFilesIterator = new CallbackFilterIterator($iterator, function(SplFileInfo $fileInfo) { return $fileInfo-&gt;isFile(); });
                • FilesystemIterator::SKIP_DOTS 标志可以与RecursiveDirectoryIterator 一起使用,而不是过滤。其他目录已经被跳过,因为RecursiveIteratorIterator 默认使用RecursiveIteratorIterator::LEAVES_ONLY 标志。
                【解决方案15】:

                我通过一次检查迭代改进了 Hors Sujet 的良好代码,以避免在结果数组中包含文件夹:

                函数 getDirContents($dir, &$results = array()){ $files = scandir($dir); foreach($files as $key => $value){ $path = realpath($dir.DIRECTORY_SEPARATOR.$value); if(is_dir($path) == false) { $结果[] = $路径; } 否则 if($value != "." && $value != "..") { getDirContents($path, $results); if(is_dir($path) == false) { $结果[] = $路径; } } } 返回$结果; }

                【讨论】:

                  【解决方案16】:

                  这里我有一个例子

                  列出使用 PHP 递归函数读取的目录 csv(file) 中的所有文件和文件夹

                  <?php
                  
                  /** List all the files and folders in a Directory csv(file) read with PHP recursive function */
                  function getDirContents($dir, &$results = array()){
                      $files = scandir($dir);
                  
                      foreach($files as $key => $value){
                          $path = realpath($dir.DIRECTORY_SEPARATOR.$value);
                          if(!is_dir($path)) {
                              $results[] = $path;
                          } else if($value != "." && $value != "..") {
                              getDirContents($path, $results);
                              //$results[] = $path;
                          }
                      }
                  
                      return $results;
                  }
                  
                  
                  
                  
                  
                  $files = getDirContents('/xampp/htdocs/medifree/lab');//here folder name where your folders and it's csvfile;
                  
                  
                  foreach($files as $file){
                  $csv_file =$file;
                  $foldername =  explode(DIRECTORY_SEPARATOR,$file);
                  //using this get your folder name (explode your path);
                  print_r($foldername);
                  
                  if (($handle = fopen($csv_file, "r")) !== FALSE) {
                  
                  fgetcsv($handle); 
                  while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
                  $num = count($data);
                  for ($c=0; $c < $num; $c++) {
                  $col[$c] = $data[$c];
                  }
                  }
                  fclose($handle);
                  }
                  
                  }
                  
                  ?>
                  

                  http://myphpinformation.blogspot.in/2016/05/list-all-files-and-folders-in-directory-csv-file-read-with-php-recursive.html

                  【讨论】:

                    【解决方案17】:

                    这是我想出的,而且代码行数不多

                    function show_files($start) {
                        $contents = scandir($start);
                        array_splice($contents, 0,2);
                        echo "<ul>";
                        foreach ( $contents as $item ) {
                            if ( is_dir("$start/$item") && (substr($item, 0,1) != '.') ) {
                                echo "<li>$item</li>";
                                show_files("$start/$item");
                            } else {
                                echo "<li>$item</li>";
                            }
                        }
                        echo "</ul>";
                    }
                    
                    show_files('./');
                    

                    它输出类似的东西

                    ..idea
                    .add.php
                    .add_task.php
                    .helpers
                     .countries.php
                    .mysqli_connect.php
                    .sort.php
                    .test.js
                    .test.php
                    .view_tasks.php
                    

                    ** 点是无序列表的点。

                    希望这会有所帮助。

                    【讨论】:

                    • 既然您在问题提出两年后添加了一个答案:为什么我要使用您的答案而不是公认的答案或惯用的 RecursiveDirectorIterator 解决方案?
                    • 几个月前我才开始学习 PHP。我搜索了这个问题的解决方案,但也试图提出我自己的解决方案。我发布它的想法是,如果我的解决方案可以帮助某人。
                    • 唯一一个在基于 IIS Windows 2012 服务器的 PHP 网站上为我工作的人
                    【解决方案18】:

                    这是我的:

                    function recScan( $mainDir, $allData = array() ) 
                    { 
                    // hide files 
                    $hidefiles = array( 
                    ".", 
                    "..", 
                    ".htaccess", 
                    ".htpasswd", 
                    "index.php", 
                    "php.ini", 
                    "error_log" ) ; 
                    
                    //start reading directory 
                    $dirContent = scandir( $mainDir ) ; 
                    
                    foreach ( $dirContent as $key => $content ) 
                    { 
                    $path = $mainDir . '/' . $content ; 
                    
                    // if is readable / file 
                    if ( ! in_array( $content, $hidefiles ) ) 
                    { 
                    if ( is_file( $path ) && is_readable( $path ) ) 
                    { 
                    $allData[] = $path ; 
                    } 
                    
                    // if is readable / directory 
                    // Beware ! recursive scan eats ressources ! 
                    else 
                    if ( is_dir( $path ) && is_readable( $path ) ) 
                    { 
                    /*recursive*/ 
                    $allData = recScan( $path, $allData ) ; 
                    } 
                    } 
                    } 
                    
                    return $allData ; 
                    }  
                    

                    【讨论】:

                      【解决方案19】:

                      这个解决方案为我完成了这项工作。 RecursiveIteratorIterator 以递归方式列出所有目录和文件,但未排序。程序过滤列表并对其进行排序。

                      我确信有办法把这个写得更短;随时改进它。 这只是一个代码sn-p。您可能想根据自己的目的来拉皮条。

                      <?php
                      
                      $path = '/pth/to/your/directories/and/files';
                      // an unsorted array of dirs & files
                      $files_dirs = iterator_to_array( new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path),RecursiveIteratorIterator::SELF_FIRST) );
                      
                      echo '<html><body><pre>';
                      // create a new associative multi-dimensional array with dirs as keys and their files
                      $dirs_files = array();
                      foreach($files_dirs as $dir){
                       if(is_dir($dir) AND preg_match('/\/\.$/',$dir)){
                        $d = preg_replace('/\/\.$/','',$dir);
                        $dirs_files[$d] = array();
                        foreach($files_dirs as $file){
                         if(is_file($file) AND $d == dirname($file)){
                          $f = basename($file);
                          $dirs_files[$d][] = $f;
                         }
                        }
                       }
                      }
                      //print_r($dirs_files);
                      
                      // sort dirs
                      ksort($dirs_files);
                      
                      foreach($dirs_files as $dir => $files){
                       $c = substr_count($dir,'/');
                       echo  str_pad(' ',$c,' ', STR_PAD_LEFT)."$dir\n";
                       // sort files
                       asort($files);
                       foreach($files as $file){
                        echo str_pad(' ',$c,' ', STR_PAD_LEFT)."|_$file\n";
                       }
                      }
                      echo '</pre></body></html>';
                      
                      ?>
                      

                      【讨论】:

                        【解决方案20】:

                        这将打印给定目录中所有文件的完整路径,您也可以将其他回调函数传递给recursiveDir。

                        function printFunc($path){
                            echo $path."<br>";
                        }
                        
                        function recursiveDir($path, $fileFunc, $dirFunc){
                            $openDir = opendir($path);
                            while (($file = readdir($openDir)) !== false) {
                                $fullFilePath = realpath("$path/$file");
                                if ($file[0] != ".") {
                                    if (is_file($fullFilePath)){
                                        if (is_callable($fileFunc)){
                                            $fileFunc($fullFilePath);
                                        }
                                    } else {
                                        if (is_callable($dirFunc)){
                                            $dirFunc($fullFilePath);
                                        }
                                        recursiveDir($fullFilePath, $fileFunc, $dirFunc);
                                    }
                                }
                            }
                        }
                        
                        recursiveDir($dirToScan, 'printFunc', 'printFunc');
                        

                        【讨论】:

                        • 或:realpath("$path/$file");
                        猜你喜欢
                        • 2011-10-30
                        • 2010-10-19
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-11-07
                        • 2010-10-04
                        • 1970-01-01
                        • 1970-01-01
                        • 2019-12-29
                        相关资源
                        最近更新 更多