PHP获取给定目录的所有子目录

179
如何获取给定目录下所有子目录但不包括文件,.(当前目录)或..(父目录),然后在函数中使用每个子目录?
16个回答

248

选项1:

你可以使用 glob() 函数,并加上 GLOB_ONLYDIR 选项来获取目录列表。

选项2:

另一个选项是使用 array_filter 对目录列表进行过滤。但请注意,下面的代码将跳过名称中带有点号(比如 .config)的有效目录。

$dirs = array_filter(glob('*'), 'is_dir');
print_r($dirs);

3
你需要在这里使用递归。 - Josef Sábl
抱歉,这里的 GLOB_ONLYDIR 选项在哪里? - brettwhiteman
6
请注意单词“or”。他提出了两种不同的实现目标的方法。 - Ken Wayne VanderLinde
8
虽然这个答案简单易懂,但它并没有回答问题:如何获取父目录下的子目录(即当前工作目录的同级目录)。要做到这一点,需要将工作目录更改为父目录。 - ryanm
2
这会忽略以点号开头的目录,例如 ".config"。 - blade
显示剩余2条评论

194

以下是如何使用GLOB仅检索目录:

$directories = glob($somePath . '/*' , GLOB_ONLYDIR);

2
这也包括主目录。 - user4951
5
这并不包括我的情况下主目录(Windows)。 - marcovtwout
3
这不包括我的 Mac 或 Linux 上的主目录。也许这与使用的路径有关? - Jake
1
这也包括输出中的路径 $somePath - The Godfather

62

Spl DirectoryIterator类提供了一种简单的界面来查看文件系统目录的内容。

$dir = new DirectoryIterator($path);
foreach ($dir as $fileinfo) {
    if ($fileinfo->isDir() && !$fileinfo->isDot()) {
        echo $fileinfo->getFilename().'<br>';
    }
}

30

和您之前的问题几乎相同:

$iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($yourStartingPath), 
            RecursiveIteratorIterator::SELF_FIRST);

foreach($iterator as $file) {
    if($file->isDir()) {
        echo strtoupper($file->getRealpath()), PHP_EOL;
    }
}

使用你想要的函数替换 strtoupper


1
好的,谢谢!还有一个问题:我怎么才能从整个路径中仅分离出子目录名呢? - Adrian M.
@Adrian,请查看我在你的另一个问题中提供的API文档。getFilename()将仅返回目录名称。 - Gordon
1
为了去掉这些点,我必须将RecursiveDirectoryIterator::SKIP_DOTS作为第二个参数添加到RecursiveDirectoryIterator构造函数中。 - colan

8

在数组中:

function expandDirectoriesMatrix($base_dir, $level = 0) {
    $directories = array();
    foreach(scandir($base_dir) as $file) {
        if($file == '.' || $file == '..') continue;
        $dir = $base_dir.DIRECTORY_SEPARATOR.$file;
        if(is_dir($dir)) {
            $directories[]= array(
                    'level' => $level
                    'name' => $file,
                    'path' => $dir,
                    'children' => expandDirectoriesMatrix($dir, $level +1)
            );
        }
    }
    return $directories;
}

//访问:

$dir = '/var/www/';
$directories = expandDirectoriesMatrix($dir);

echo $directories[0]['level']                // 0
echo $directories[0]['name']                 // pathA
echo $directories[0]['path']                 // /var/www/pathA
echo $directories[0]['children'][0]['name']  // subPathA1
echo $directories[0]['children'][0]['level'] // 1
echo $directories[0]['children'][1]['name']  // subPathA2
echo $directories[0]['children'][1]['level'] // 1

展示所有的示例:

function showDirectories($list, $parent = array())
{
    foreach ($list as $directory){
        $parent_name = count($parent) ? " parent: ({$parent['name']}" : '';
        $prefix = str_repeat('-', $directory['level']);
        echo "$prefix {$directory['name']} $parent_name <br/>";  // <-----------
        if(count($directory['children'])){
            // list the children directories
            showDirectories($directory['children'], $directory);
        }
    }
}

showDirectories($directories);

// pathA
// - subPathA1 (parent: pathA)
// -- subsubPathA11 (parent: subPathA1)
// - subPathA2 
// pathB
// pathC

7

尝试这段代码:

<?php
$path = '/var/www/html/project/somefolder';

$dirs = array();

// directory handle
$dir = dir($path);

while (false !== ($entry = $dir->read())) {
    if ($entry != '.' && $entry != '..') {
       if (is_dir($path . '/' .$entry)) {
            $dirs[] = $entry; 
       }
    }
}

echo "<pre>"; print_r($dirs); exit;

4
您可以尝试使用此函数(需要PHP 7)
function getDirectories(string $path) : array
{
    $directories = [];
    $items = scandir($path);
    foreach ($items as $item) {
        if($item == '..' || $item == '.')
            continue;
        if(is_dir($path.'/'.$item))
            $directories[] = $item;
    }
    return $directories;
}

3

非递归列出仅目录

唯一有人提出的问题被错误地关闭了,所以我不得不在这里发表。

它还提供了筛选目录的功能。

/**
 * Copyright © 2020 Theodore R. Smith <https://www.phpexperts.pro/>
 * License: MIT
 *
 * @see https://dev59.com/enE85IYBdhLWcg3w9onw#61168906
 *
 * @param string $path
 * @param bool   $recursive Default: false
 * @param array  $filtered  Default: [., ..]
 * @return array
 */
function getDirs($path, $recursive = false, array $filtered = [])
{
    if (!is_dir($path)) {
        throw new RuntimeException("$path does not exist.");
    }

    $filtered += ['.', '..'];

    $dirs = [];
    $d = dir($path);
    while (($entry = $d->read()) !== false) {
        if (is_dir("$path/$entry") && !in_array($entry, $filtered)) {
            $dirs[] = $entry;

            if ($recursive) {
                $newDirs = getDirs("$path/$entry");
                foreach ($newDirs as $newDir) {
                    $dirs[] = "$entry/$newDir";
                }
            }
        }
    }

    return $dirs;
}


3
这是一行代码:

原始答案

 $sub_directories = array_map('basename', glob($directory_path . '/*', GLOB_ONLYDIR));

2
<?php
    /*this will do what you asked for, it only returns the subdirectory names in a given
      path, and you can make hyperlinks and use them:
    */

    $yourStartingPath = "photos\\";
    $iterator = new RecursiveIteratorIterator( 
        new RecursiveDirectoryIterator($yourStartingPath),  
        RecursiveIteratorIterator::SELF_FIRST);

    foreach($iterator as $file) { 
        if($file->isDir()) { 
            $path = strtoupper($file->getRealpath()) ; 
            $path2 = PHP_EOL;
            $path3 = $path.$path2;

            $result = end(explode('/', $path3)); 

            echo "<br />". basename($result );
        } 
    } 

    /* best regards,
        Sanaan Barzinji
        Erbil
    */
?>

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