使用PHP glob获取具有无限深度的文件夹

14

我有一个可行的函数,可以找到文件夹并创建一个数组。

function dua_get_files($path)
{
    foreach (glob($path . "/*", GLOB_ONLYDIR) as $filename)
    {
        $dir_paths[] = $filename;   
    }
    return $dir_paths;
}

这个函数只能找到当前位置下的目录。我想要在子文件夹及其子文件夹中找到目录路径。

这个数组仍应该是一个扁平的目录路径列表。

输出数组应该如何呈现的示例

$dir_path[0] = 'path/folder1';
$dir_path[1] = 'path/folder1/child_folder1';
$dir_path[2] = 'path/folder1/child_folder2';
$dir_path[3] = 'path/folder2';
$dir_path[4] = 'path/folder2/child_folder1';
$dir_path[5] = 'path/folder2/child_folder2';
$dir_path[6] = 'path/folder2/child_folder3';
6个回答

20

如果您想要递归地处理目录,那么您应该查看RecursiveDirectoryIterator

$path = realpath('/etc');

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
    echo "$name\n";
}

@Davood 因为使用该迭代器,无需自己进行递归 ;-)@Jens 您的编辑正在等待批准,并需要一个“批准投票”才能显示;如果不久将其批准,我将自行编辑以添加您发布的内容;谢谢! - Pascal MARTIN
这个类被禁用或未定义的可能性非常低:它是由 PHP >= 5.1 提供的标准类;而且几乎没有安全原因可以禁用它。 - Pascal MARTIN
我宁愿不能使用这个类,因为如果可能的话,不使用这个类是没有必要的。 - DJafari
1
我不确定我真正理解你的意思;但是如果PHP提供这样的类,为什么不直接使用它们呢? - Pascal MARTIN
1
嗯...如果你的服务器没有PHP >= 5.1.2(这已经超过多年了!),那么你会遇到问题^^ PHP 5.2(尤其是5.2.17)本身已经到了生命周期的尽头...如果你认为你必须编写与PHP < 5.1兼容的代码,那么,祝你好运!(实际上我不想处在你的位置) - Pascal MARTIN
显示剩余3条评论

10

非常奇怪 - 每个人都建议使用递归,但最好还是用循环:

$dir ='/dir';
while($dirs = glob($dir . '/*', GLOB_ONLYDIR)) {
  $dir .= '/*';
  if(!$result) {
     $result = $dirs;
   } else {
      $result = array_merge($result, $dirs);
   }
}

3
好的!但是,当然,并没有什么“非常奇怪”的事情:使用递归过程来迭代递归结构可能是最显而易见的做法。 - Sz.

6
尝试使用以下内容:
function dua_get_files($path)
{
    $data = array();
    $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);

    foreach ($files as $file)
    {
        if (is_dir($file) === true)
        {
            $data[] = strval($file);
        }
    }

    return $data;
}

1
@DennisMeissner:似乎这个答案并不是被接受的,但它显然可以胜任。使用glob来完成这个任务是毫无意义的。 - Alix Axel

4
使用此函数:

function dua_get_files($path)
{
    $dir_paths = array();
    foreach (glob($path . "/*", GLOB_ONLYDIR) as $filename)
    {
        $dir_paths[] = $filename;
        $a = glob("$filename/*", GLOB_ONLYDIR);
        if( is_array( $a ) )
        {
            $b = dua_get_files( "$filename/*" );
            foreach( $b as $c )
            {
                $dir_paths[] = $c;
            }
        }
    }
    return $dir_paths;
}

1

您可以使用php GLOB函数,但必须创建一个递归函数以扫描无限级别深度的目录。然后将结果存储在全局变量中。

function dua_get_files($path) {
    global $dir_paths; //global variable where to store the result
    foreach ($path as $dir) { //loop the input
        $dir_paths[] = $dir; //can use also "basename($dir)" or "realpath($dir)"
        $subdir =  glob($dir . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR); //use DIRECTORY_SEPARATOR to be OS independent
        if (!empty($subdir)) { //if subdir is not empty make function recursive
            dua_get_files($subdir); //execute the function again with current subdir
        }
    }
}

//usage:
$path = array('galleries'); //suport absolute or relative path. support one or multiple path
dua_get_files($path);
print('<pre>'.print_r($dir_paths,true).'</pre>'); //debug

0

对于PHP,如果您使用的是Linux/Unix系统,您还可以使用反引号(shell执行)与Unix find命令。在文件系统上进行目录搜索可能需要很长时间并且会遇到循环 - 系统find命令已经构建为快速处理文件系统循环。换句话说,系统exec调用可能比使用PHP本身搜索文件系统树要少得多的CPU时间。

$dirs = `find $path -type d`;

记得对 $path 输入进行清理处理,以避免其他用户传入安全威胁的路径名称(例如来自网址等)。

将其放入数组中

$dirs = preg_split("/\s*\n+\s*/",`find $path -type d`,-1,PREG_SPLIT_NO_EMPTY);

这个答案是跨版本、递归和权限容忍的(前提是服务器没有以root身份运行apache/php-fpm)。即使在PHP 3上运行,它也可以产生正确的结果!你可以通过传递正确的参数来预订find-result来优先查找。与PHP中的目录递归相比,unix find明显更快。 - Beracah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接