PHP scandir递归

GRX*_*GRX 3 php file scandir

我希望我的脚本以递归方式进行scandir,

$files = scandir('/dir');
foreach($files as $file){
if(is_dir($file)){
    echo '<li><label class="tree-toggler nav-header"><i class="fa fa-folder-o"></i>'.$file.'</label>';
    $subfiles = scandir($rooturl.'/'.$file);
        foreach($subfiles as $subfile){
            // and so on and on and on
        }
        echo '<li>';
    } else {
        echo $file.'<br />';
    }
}
Run Code Online (Sandbox Code Playgroud)

我想循环这个方式,对于scandir找到的每个目录,它在该目录中找到的文件夹上运行另一个scandir,

所以dir'A'包含目录1/2/3,它现在应该scandir(1),scandir(2),scandir(3)等等,每个目录都找到了.

如何轻松地实现这一点,而无需在每个foreach中反复粘贴代码?

编辑:由于答案几乎与我已经尝试的一样,我会稍微更新一下这个问题.

使用此脚本,我需要创建一个树视图列表.使用当前发布的脚本,以下get的回声发生:

/images/dir1/file1.png
/images/dir1/file2.png
/images/dir1/file3.png
/images/anotherfile.php
/data/uploads/avatar.jpg
/data/config.php
index.php
Run Code Online (Sandbox Code Playgroud)

我真正需要的是:

<li><label>images</label>
    <ul>
        <li><label>dir1</label>
            <ul>
                <li>file1.png</li>
                <li>file2.png</li>
                <li>file3.png</li>
            </ul>
        </li>
        <li>anotherfile.php</li>
    </ul>
</li>
<li><label>data</label>
    <ul>
        <li><label>uploads</label>
            <ul>
                <li>avatar.jpg</li>
            </ul>
        </li>
        <li>config.php</li>
    </ul>
</li>
<li>index.php</li>
Run Code Online (Sandbox Code Playgroud)

等等,谢谢你已经发布的答案!

All*_*nde 9

我知道这是一个老问题,但我写了一个更实用的版本.它不使用全局状态并使用纯函数来解决问题:

function scanAllDir($dir) {
  $result = [];
  foreach(scandir($dir) as $filename) {
    if ($filename[0] === '.') continue;
    $filePath = $dir . '/' . $filename;
    if (is_dir($filePath)) {
      foreach (scanAllDir($filePath) as $childFilename) {
        $result[] = $filename . '/' . $childFilename;
      }
    } else {
      $result[] = $filename;
    }
  }
  return $result;
}
Run Code Online (Sandbox Code Playgroud)

  • 您可能希望使用常量 DIRECTORY_SEPARATOR 而不是硬编码“/”,以便在 Linux 和 Windows 系统上安全使用代码。 (2认同)

mat*_*uda 7

上一个函数的变体,使用三元运算符使函数更短,并使用 splat(或 spread)运算符为 array_push 解压数组。

function getFiles(string $directory): array
{
    $files = array_diff(scandir($directory), ['.', '..']);
    $allFiles = [];

    foreach ($files as $file) {
        $fullPath = $directory. DIRECTORY_SEPARATOR .$file;
        is_dir($fullPath) ? array_push($allFiles, ...getFiles($fullPath)) : array_push($allFiles, $file);
    }

    return $allFiles;
}
Run Code Online (Sandbox Code Playgroud)

老的

function getFiles(string $directory, array $allFiles = []): array
{
    $files = array_diff(scandir($directory), ['.', '..']);

    foreach ($files as $file) {
        $fullPath = $directory. DIRECTORY_SEPARATOR .$file;

        if( is_dir($fullPath) )
            $allFiles += getFiles($fullPath, $allFiles);
        else
            $allFiles[] = $file;
    }

    return $allFiles;
}
Run Code Online (Sandbox Code Playgroud)

我知道这已经很旧了,但我想展示其他答案的略有不同的版本。使用 array_diff 丢弃“.” 和“..”文件夹。还有用于组合 2 个数组的 + 运算符(我很少看到它被使用,所以它可能对某人有用)


Fra*_*nco 5

您可以通过这种方式递归扫描目录,目标是您最顶层的目录:

function scanDir($target) {

        if(is_dir($target)){

            $files = glob( $target . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned

            foreach( $files as $file )
            {
                scanDir( $file );
            }


        } 
    }
Run Code Online (Sandbox Code Playgroud)

您可以轻松地根据需要调整此功能。例如,如果要使用它来删除目录及其内容,您可以执行以下操作:

function delete_files($target) {

        if(is_dir($target)){

            $files = glob( $target . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned

            foreach( $files as $file )
            {
                delete_files( $file );
            }

            rmdir( $target );

        } elseif(is_file($target)) {

            unlink( $target );
    }
Run Code Online (Sandbox Code Playgroud)

你不能以你正在做的方式做到这一点。以下函数以递归方式获取所有目录、子目录以及您想要的深度及其内容:

function assetsMap($source_dir, $directory_depth = 0, $hidden = FALSE)
    {
        if ($fp = @opendir($source_dir))
        {
            $filedata   = array();
            $new_depth  = $directory_depth - 1;
            $source_dir = rtrim($source_dir, '/').'/';

            while (FALSE !== ($file = readdir($fp)))
            {
                // Remove '.', '..', and hidden files [optional]
                if ( ! trim($file, '.') OR ($hidden == FALSE && $file[0] == '.'))
                {
                    continue;
                }

                if (($directory_depth < 1 OR $new_depth > 0) && @is_dir($source_dir.$file))
                {
                    $filedata[$file] = assetsMap($source_dir.$file.'/', $new_depth, $hidden);
                }
                else
                {
                    $filedata[] = $file;
                }
            }

            closedir($fp);
            return $filedata;
        }
        echo 'can not open dir';
        return FALSE;
    }
Run Code Online (Sandbox Code Playgroud)

将您的路径传递给函数:

$path = 'elements/images/';
$filedata = assetsMap($path, $directory_depth = 5, $hidden = FALSE);
Run Code Online (Sandbox Code Playgroud)

$filedata is than an array with all founded directories and sub directories with their content. This function lets you scan the directories structure ($directory_depth) so deep as you want as well get rid of all the boring hidden files (e.g. '.','..')

All you have to do now is to use the returned array, which is the complete tree structure, to arrange the data in your view as you like.

What you are trying to do is in fact a kind of file manager and as you know there are a lot of those in the wild, open source and free.

I hope this will help you and I wish you a merry Christmas.


小智 5

现代方式:

use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;

$path = '/var/www/path/to/your/files/';

foreach ( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path, RecursiveDirectoryIterator::SKIP_DOTS ) ) as $file ) {
    
    // TODO: Uncomment to see additional information. Do your manipulations with the files here.
    // var_dump( $file->getPathname() ); // Or simple way: echo $file;
    // var_dump( $file->isFile() );
    // var_dump( $file->isDir() );
    // var_dump( $file->getFileInfo() );
    // var_dump( $file->getExtension() );
    // var_dump( $file->getDepth() );

}
Run Code Online (Sandbox Code Playgroud)