Рекурсия по дереву каталогов в PHP - PullRequest
2 голосов
/ 27 марта 2010

У меня есть набор папок с глубиной не менее 4 или 5 уровней. Я пытаюсь пройтись по дереву каталогов как можно глубже и перебрать каждый файл. Я получил код для перехода к первым наборам подкаталогов, но не более подробно, и я не уверен, почему. Есть идеи?

$count = 0;
$dir = "/Applications/MAMP/htdocs/site.com";
function recurseDirs($main, $count){
    $dir = "/Applications/MAMP/htdocs/site.com";
    $dirHandle = opendir($main);
    echo "here";
    while($file = readdir($dirHandle)){
        if(is_dir($file) && $file != '.' && $file != '..'){
            echo "isdir";
            recurseDirs($file);
        }
        else{
            $count++;
            echo "$count: filename: $file in $dir/$main \n<br />";
        }
    }
}
recurseDirs($dir, $count);

Ответы [ 4 ]

17 голосов
/ 27 марта 2010

Проверьте новый RecursiveDirectoryIterator .

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

В руководстве есть несколько простых примеров, с которых можно начать:

<?php

$path = realpath('/etc');

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), 
RecursiveIteratorIterator::SELF_FIRST);

foreach($objects as $name => $object){
    echo "$name\n";
}

?>
2 голосов
/ 27 марта 2010

Ошибка при звонке

recurseDirs($file);

и

is_dir($file)

Вы должны указать полный путь:

recurseDirs($main . '/' .$file, $count);

и

is_dir($main . '/' .$file)

Однако, как и другие авторы, я предлагаю использовать RecursiveDirectoryIteretor.

0 голосов
/ 18 января 2013

Так что да: сегодня я ленился и гуглил решение для резака печенья для рекурсивного списка каталогов и наткнулся на это. Когда я закончил писать свою собственную функцию (относительно того, почему я даже потратил время на Google, потому что это вне меня - я всегда чувствую необходимость заново изобретать колесо без какой-либо подходящей причины), я был склонен поделиться своим мнением на этом.

Несмотря на то, что существуют мнения за и против использования RecursiveDirectoryIterator, я просто опубликую свой взгляд на простую рекурсивную функцию каталога и избегу политики включения в RecursiveDirectoryIterator.

Вот оно:

function recursiveDirectoryList( $root )
{

    /* 
     * this next conditional isn't required for the code to function, but I
     * did not want double directory separators in the resulting array values 
     * if a trailing directory separator was provided in the root path;
     * this seemed an efficient manner to remedy said problem easily...
     */
    if( substr( $root, -1 ) === DIRECTORY_SEPARATOR )
    {
        $root = substr( $root, 0, strlen( $root ) - 1 );
    }

    if( ! is_dir( $root ) ) return array();

    $files = array();
    $dir_handle = opendir( $root );

    while( ( $entry = readdir( $dir_handle ) ) !== false )
    {

        if( $entry === '.' || $entry === '..' ) continue;

        if( is_dir( $root . DIRECTORY_SEPARATOR . $entry ) )
        {
            $sub_files = recursiveDirectoryList( 
                $root . 
                DIRECTORY_SEPARATOR . 
                $entry . 
                DIRECTORY_SEPARATOR 
            );
            $files = array_merge( $files, $sub_files );
        }
        else
        {
            $files[] = $root . DIRECTORY_SEPARATOR . $entry;
        }
    }

    return (array) $files;

}

С помощью этой функции ответ о получении количества файлов прост:

$dirpath = '/your/directory/path/goes/here/';

$files = recursiveDirectoryList( $dirpath );

$number_of_files = sizeof( $files );

Но, если вам не нужны служебные данные массива соответствующих путей к файлам - или просто вам это не нужно - нет необходимости передавать счет в рекурсивную функцию, как было рекомендовано.

Можно просто изменить мою исходную функцию, чтобы выполнить подсчет следующим образом:

function recursiveDirectoryListC( $root )
{

    $count = 0;

    if( ! is_dir( $root ) ) return (int) $count;

    $dir_handle = opendir( $root );

    while( ( $entry = readdir( $dir_handle ) ) !== false )
    {

        if( $entry === '.' || $entry === '..' ) continue;

        if( is_dir( $root . DIRECTORY_SEPARATOR . $entry ) )
        {
            $count += recursiveDirectoryListC(
                $root .
                DIRECTORY_SEPARATOR .
                $entry .
                DIRECTORY_SEPARATOR
            );
        }
        else
        {
            $count++;
        }

    }

    return (int) $count;

}

В обеих этих функциях функция opendir () действительно должна быть заключена в условие, если каталог не читается или возникает другая ошибка. Обязательно сделайте это правильно:

if( ( $dir_handle = opendir( $dir ) ) !== false ) 
{ 
    /* perform directory read logic */ 
}
else
{
    /* do something on failure */
}

Надеюсь, это кому-нибудь поможет ...

0 голосов
/ 27 марта 2010

Вызов is_dir и recurseDirs не полностью корректен.Кроме того, ваш подсчет не работает правильно.Это работает для меня:

$dir = "/usr/";
function recurseDirs($main, $count=0){
    $dirHandle = opendir($main);
    while($file = readdir($dirHandle)){
        if(is_dir($main.$file."/") && $file != '.' && $file != '..'){
            echo "Directory {$file}: <br />";
            $count = recurseDirs($main.$file."/",$count); // Correct call and fixed counting
        }
        else{
            $count++;
            echo "$count: filename: $file in $main \n<br />";
        }
    }
    return $count;
}
$number_of_files = recurseDirs($dir);

Обратите внимание на измененные вызовы функции выше и новое возвращаемое значение функции.

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