Рекурсивное добавление всех подкаталогов и файлов из каталога в массив - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть функция, которая будет получать все каталоги и файлы из заданного каталога, однако способ их получения усложняет работу с:

function getFileLists($dir, $recursive=FALSE) {
    // retrieve an array of all the directories and files in a certain directory
    $retval = [];
    if (substr($dir, -1) !== "/") {
        $dir .= "/";
    }
    $d = @dir($dir) or die("unable to open {$dir} for reading, permissions?");
    while(FALSE !== ($entry = $d->read())) {
        if ($entry{0} === ".") { continue; }
        if (is_dir("{$dir}{$entry}")) {
            $retval[] = [
                'name' => "{$dir}{$entry}",
                'last_modified' => filemtime("{$dir}{$entry}")
            ];
            if($recursive && is_readable("{$dir}{$entry}/")) {
                $retval = array_merge($retval, getFileLists("{$dir}{$entry}/", TRUE));
            }
        } elseif (is_readable("{$dir}{$entry}")) {
            $retval[] = [
                'name' => "{$dir}{$entry}",
                'last_modified' => filemtime("{$dir}{$entry}")
            ];
        }
    }
    $d->close();
    return $retval;
}

Когда вы запускаете это надля данного каталога он даст следующие результаты:

array(14) {
  [0]=>
  array(2) {
    ["name"]=>
    string(15) "./kb_data/admin"
    ["last_modified"]=>
    int(1543591247)
  }
  [1]=>
  array(2) {
    ["name"]=>
    string(28) "./kb_data/admin/testfile.txt"
    ["last_modified"]=>
    int(1543591238)
  }
  ...
}

Это замечательно, но из-за этого довольно сложно работать с тем, как я хочу отобразить этот каталог как tree.На самом деле я хочу сделать что-то вроде следующего:

array(14) {
  [0]=>
    array(3) {
    ["name"]=>
    string(16) "./kb_data/shared"
    ["last_modified"]=>
    int(1543591258)
    ["files"] => array(#) {
        ["name"]=>
        string(29) "./kb_data/shared/testfile.txt"
        ["last_modified"]=>
        int(1543591238)
     }
  }
  ...
}

Как вы можете видеть, я хочу, чтобы каждый файл в каталоге находился внутри каталога.Как я могу провести рефакторинг этой функции, чтобы получить желаемый результат?

Ответы [ 4 ]

0 голосов
/ 05 декабря 2018

Простой, но полный пример, который использует DirectoryIterator для перечисления всех файлов в каталоге и рекурсии, чтобы избежать необходимости манипулировать рекурсивными данными итератора, чтобы получить всю необходимую информацию.Что мне нравится в DirectoryIterator, так это то, что это дает объект, из которого вы можете извлечь множество деталей файлов (например, время последнего изменения с использованием getMTime()).

function buildTree ( $path )    {
    $paths = [];
    foreach (new DirectoryIterator ($path) as $file) {
        if ( !$file->isDot() )   {
            $newFile = ["name" => $file->getRealPath(),
                "last_modified" => $file->getMTime()];
            if ($file->isDir()) {
                $newFile["files"] = buildTree($file->getRealPath());
            }
            $paths[] = $newFile;
        }
    }
    return $paths;
}
$paths = buildTree($root);
0 голосов
/ 04 декабря 2018

Как насчет (SPL) итератора каталогов

function getFileLists($dir) {
    $rec = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::SELF_FIRST);
    $ar = array();
    foreach ($rec as $splFileInfo) {
       $path = $splFileInfo->isDir()
             ? array($splFileInfo->getFilename() => array())
             : array($splFileInfo->getFilename());

       for ($depth = $rec->getDepth() - 1; $depth >= 0; $depth--) {
           $path = array($rec->getSubIterator($depth)->current()->getFilename() => $path);
       }
       $ar = array_merge_recursive($ar, $path);
    }
    return $ar;
}
print "<pre>";
print_r(getFileLists("/Library/WebServer/Documents/am-web/"));
0 голосов
/ 04 декабря 2018

Лично я хотел бы, чтобы все было просто, вытащил это из моей личной библиотеки, возможно, не самый лучший ответ, но он добился цели

<?php
function glob_recursive($dir, $recursive = false) {
    $files = [];
    foreach (glob($dir  . DIRECTORY_SEPARATOR . '*') as $object) {
        if (in_array($object, ['.', '..'])) {
            continue;
        }
        $file = [];
        $file['name'] = $object;
        if (false !== $recursive && is_dir($object)) {
            $file['files'] = glob_recursive($object);
        }
        $files[] = $file;
    }
    return $files;
}
$dir = __DIR__;
$list = glob_recursive($dir);
0 голосов
/ 30 ноября 2018

Я бы удалил параметр "recursive" и попробовал бы что-то вроде этого:

function getFileLists($dir)
{
    echo "Processing $dir\n";

    // retrieve an array of all the directories and files in a certain directory
    $retval = [];
    if (substr($dir, -1) !== "/") {
        $dir .= "/";
    }
    $d = @dir($dir) or die("unable to open {$dir} for reading, permissions?");
    while (false !== ($entry = $d->read())) {
        if ($entry{0} === ".") {
            continue;
        }
        if (is_dir("{$dir}{$entry}")) {
            $retval[] = [
                'name'          => "{$dir}{$entry}",
                'last_modified' => filemtime("{$dir}{$entry}"),
                //recursive call 
                'files'         => array_merge($retval, getFileLists("{$dir}{$entry}/"))
            ];
        } elseif (is_readable("{$dir}{$entry}")) {
            $retval[] = [
                'name'          => "{$dir}{$entry}",
                'last_modified' => filemtime("{$dir}{$entry}")
            ];
        }
    }
    $d->close();

    return $retval;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...