Подтвердить что ты не робот

Рекурсивный массив структуры каталогов в PHP

Я пытаюсь поместить некоторые папки на мой жесткий диск в массив.

Например, фотографии каникул. Пусть говорят, что у нас есть эта структура:

  • Установить 1
    • Пункт 1 набора 1
    • Пункт 2 набора 1
    • Пункт... набора 1
  • Установить 2
    • Подмножество 1 из набора 2
      • Пункт 1 подмножества 1 набора 2
      • Пункт... подмножества 1 набора 2
    • Подмножество 2 набора 2
    • Случайный файл, а не каталог.
  • Установить 3
  • ...

Я хочу иметь что-то подобное, как массив.
Значение У меня есть 1 большой массив, и в этом массиве больше массивов. Каждый набор и подмножество получает свой собственный массив.

Я пытаюсь сделать это примерно так:

Array
(
    [Set 1] => Array([0] => Item 1 of Set 1, [1] => Item 1 of Set 1,...)
    [Set 2] => Array([Subnet 1] => Array([0] => Item 1 of Subset 1 of Set 2,[1] => ...), [Subnet 2] => Array([0] => ..., ..., ...), ..., [0] => Random File)
    [set 3] => Array(...)
    ...
)

Я наткнулся на это: http://www.the-art-of-web.com/php/dirlist/

Но это не то, что я ищу. Я вмешивался в это, но это не давало мне ничего, кроме неприятностей.

Вот пример, источник просмотра для большего разрешения (без щелчка, по-видимому...). Example

4b9b3361

Ответ 1

Я рекомендую использовать DirectoryIterator для создания вашего массива

Вот фрагмент, который я собрал вместе быстро, но у меня нет среды для его проверки, поэтому будьте готовы его отладить.

$fileData = fillArrayWithFileNodes( new DirectoryIterator( '/path/to/root/' ) );

function fillArrayWithFileNodes( DirectoryIterator $dir )
{
  $data = array();
  foreach ( $dir as $node )
  {
    if ( $node->isDir() && !$node->isDot() )
    {
      $data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
    }
    else if ( $node->isFile() )
    {
      $data[] = $node->getFilename();
    }
  }
  return $data;
}

Ответ 2

Простая реализация без обработки ошибок:

function dirToArray($dir) {
    $contents = array();
    # Foreach node in $dir
    foreach (scandir($dir) as $node) {
        # Skip link to current and parent folder
        if ($node == '.')  continue;
        if ($node == '..') continue;
        # Check if it a node or a folder
        if (is_dir($dir . DIRECTORY_SEPARATOR . $node)) {
            # Add directory recursively, be sure to pass a valid path
            # to the function, not just the folder name
            $contents[$node] = dirToArray($dir . DIRECTORY_SEPARATOR . $node);
        } else {
            # Add node, the keys will be updated automatically
            $contents[] = $node;
        }
    }
    # done
    return $contents;
}

Ответ 3

На основе кода @soulmerge answer. Я просто удалил несколько нит и комментариев и использовал $startpath в качестве моего стартового каталога. (СПАСИБО: @soulmerge!)

function dirToArray($dir) {
    $contents = array();
    foreach (scandir($dir) as $node) {
        if ($node == '.' || $node == '..') continue;
        if (is_dir($dir . '/' . $node)) {
            $contents[$node] = dirToArray($dir . '/' . $node);
        } else {
            $contents[] = $node;
        }
    }
    return $contents;
}

$r = dirToArray($startpath);
print_r($r);

Ответ 4

У меня был успех с пакетом PEAR File_Find, в частности метод mapTreeMultiple(). Ваш код станет чем-то вроде:

require_once 'File/Find.php';
$fileList = File_Find::mapTreeMultiple($dirPath);

Это должно возвращать массив, аналогичный тому, о котором вы просите.

Ответ 5

Итак, 6 лет спустя....

Мне нужно решение, подобное ответам @tim & @soulmerge. Я пытался сделать массовые шаблоны php UnitTest для всех файлов php в папках codeigniter по умолчанию.

Это был первый шаг в моем процессе, чтобы получить полное рекурсивное содержимое каталога/папки в виде массива. Затем воссоздайте структуру файлов, и внутри каталогов есть файлы с правильным именем, структурой классов, скобками, методами и разделами комментариев, готовыми для заполнения для php UnitTest.

Подводя итог: дайте имя каталога, получите однослойный массив всех каталогов в нем в виде ключей и всех файлов в качестве значений.

Я расширил их ответ немного дальше, и вы получите следующее:

function getPathContents($path)
{
     // was a file path provided?
     if ($path === null){
        // default file paths in codeigniter 3.0
        $dirs = array(
            './models',
            './controllers'
        );
    } else{
        // file path was provided
        // it can be a comma separated list or singular filepath or file
        $dirs = explode(',', $path);
    }
    // final array
    $contents = array();
    // for each directory / file given
    foreach ($dirs as $dir) {
        // is it a directory?
        if (is_dir($dir)) {
            // scan the directory and for each file inside
            foreach (scandir($dir) as $node) {
                // skip current and parent directory
                if ($node === '.' || $node === '..') {
                    continue;
                } else {
                    // check for sub directories
                    if (is_dir($dir . '/' . $node)) {
                        // recursive check for sub directories
                        $recurseArray = getPathContents($dir . '/' . $node);
                        // merge current and recursive results
                        $contents = array_merge($contents, $recurseArray);
                    } else {
                        // it a file, put it in the array if it extension is '.php'
                        if (substr($node, -4) === '.php') {
                            // don'r remove periods if current or parent directory was input
                            if ($dir === '.' || $dir === '..') {
                                $contents[$dir][] = $node;
                            } else {
                                // remove period from directory name 
                                $contents[str_replace('.', '', $dir)][] = $node;
                            }
                        }
                    }
                }
            }
        } else {
            // file name was given
            $contents[] = $dir; 
        }
    }
    return $contents;
}