PHP - 在下拉菜单中递归列出所有目录和子目录

14

可能是重复问题:
PHP 获取给定目录下的所有子目录

我想要一个下拉菜单来显示./files/$userid/中所有子目录,而不仅仅是主文件夹。例如:/files/$userid/folder1/folder2/

我的当前代码为:

HTML:

<select name="myDirs">
<option value=""  selected="selected">Select a folder</option>

PHP:

if (chdir("./files/" . $userid)) {

       $dirs = glob('*', GLOB_ONLYDIR);
       foreach($dirs as $val){
          echo '<option value="'.$val.'">'.$val."</option>\n";
       }        
        } else {
       echo 'Changing directory failed.';
}

你的问题是什么?请记住,制定需求并不是一个编程问题。我建议你先在网站上搜索你的需求,因为列出目录已经被问答过了。那么为什么不去酒吧坐一下,点一杯饮料呢? - hakre
你需要使用PHP的本地RecursiveDirectoryIterator类。这个答案应该会有所帮助。 - hohner
我尝试了这个http://pastebin.com/fpJiiCbZ,但它不起作用。这是我得到的输出:http://i.imgur.com/gWt3U.png - Brian
我已经做了,我不想获取文件名,只想获取文件夹。回答中的'work.txt'是什么?(复制粘贴代码返回空的下拉列表) - Brian
好的,我按照你告诉我的方式进行了一些修改,现在它可以工作了。但是我想问一个问题。下拉列表中的值被列出来了,例如/files/14/blabla被显示了多次。这是为什么?这里有一张截图以便理解... 代码:http://pastebin.com/cGKRkJzn 图片:http://i.imgur.com/8HY8a.png 。有没有一种方法可以抑制显示根文件夹? - Brian
显示剩余4条评论
3个回答

53

RecursiveDirectoryIterator应该能胜任。不幸的是,文档不太好,所以这里有一个例子:

$root = '/etc';

$iter = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($root, RecursiveDirectoryIterator::SKIP_DOTS),
    RecursiveIteratorIterator::SELF_FIRST,
    RecursiveIteratorIterator::CATCH_GET_CHILD // Ignore "Permission denied"
);

$paths = array($root);
foreach ($iter as $path => $dir) {
    if ($dir->isDir()) {
        $paths[] = $path;
    }
}

print_r($paths);

这会在我的电脑上生成以下输出:

Array
(
    [0] => /etc
    [1] => /etc/rc2.d
    [2] => /etc/luarocks
    ...
    [17] => /etc/php5
    [18] => /etc/php5/apache2
    [19] => /etc/php5/apache2/conf.d
    [20] => /etc/php5/mods-available
    [21] => /etc/php5/conf.d
    [22] => /etc/php5/cli
    [23] => /etc/php5/cli/conf.d
    [24] => /etc/rc4.d
    [25] => /etc/minicom
    [26] => /etc/ufw
    [27] => /etc/ufw/applications.d
    ...
    [391] => /etc/firefox
    [392] => /etc/firefox/pref
    [393] => /etc/cron.d
)

谢谢 @PleaseStand,它工作得很好,只需要再加一个 foreach 循环用于列表视图,就像你的输出一样。 - asi_x
不错。如果您能说明如何过滤掉隐藏文件夹及其内容(例如.svn),那就更好了。 - Raptor
对我来说不起作用...即使在目录计数仅为1000时,超时设置为一小时也会超时。 - Flash Thunder

13
你可以编写自己的递归目录列表,例如:
function expandDirectories($base_dir) {
      $directories = array();
      foreach(scandir($base_dir) as $file) {
            if($file == '.' || $file == '..') continue;
            $dir = $base_dir.DIRECTORY_SEPARATOR.$file;
            if(is_dir($dir)) {
                $directories []= $dir;
                $directories = array_merge($directories, expandDirectories($dir));
            }
      }
      return $directories;
}

$directories = expandDirectories(dirname(__FILE__));
print_r($directories);

2
这是一个很棒的 PHP 解决方案,不使用外部库。 - Katushai
与被接受的答案相比,终端命令:time php -f test.php,这个更快。 - Jonatas Walker

3
您可以使用递归通配符实现,就像这个函数中的实现一样:
function rglob($pattern='*', $path='', $flags = 0) {
$paths=glob($path.'*', GLOB_MARK|GLOB_ONLYDIR|GLOB_NOSORT);
$files=glob($path.$pattern, $flags);
foreach ($paths as $path) {
  $files=array_merge($files,rglob($pattern, $path, $flags));
}
return $files;
}

@user183391 列出文件或文件夹吗? - Brian
你可以在$flags参数中使用GLOB_ONLYDIR。 - Alex

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