обход директорий и всех поддиректорий без рекурсии

berkut

Новичок
обход директорий и всех поддиректорий без рекурсии

сабж. где-то проскакивало подобное, без использования рекурсии, а сейчас не найду никак. а сам написать не могу в силу своей ограниченности.
 

dimagolov

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

kruglov

Новичок
Надо просто понять, что такое рекурсия, и реализовать без оной, эмулируя вложенность и возвраты.

-~{}~ 04.02.08 16:40:

яндекс: нерекурсивный алгоритм
 

berkut

Новичок
вся фишка, что там говорилось(а пост на этом форуме был), что тот вариант гораздо менее русурсоёмкий.. вот и подумалось, в академических целях изучить
 

dimagolov

Новичок
ну делай массивы:
1. масив массивов содержимого директорий
2. масив обработаных позиций в директориях
они всегда имеют равную длину
обходишь массив, как находишь директорию в нем, так запрашиваешь ее содержимое, push его в 1, push 0 в 2, начали цикл по последней в стеке директории. если прошли директорию до конца делаем pop и продолжаем обходить последнюю с запомненной позиции.
 

phprus

Moderator
Команда форума
berkut
Вот то что я придумал:
Берем 2 массива. первый это массив файлов, а второй массив полных путей к каталогам где мы еще не были.

Перед циклом помещаем во второй массив путь который все подкаталоги которого надо обойти.

Далее в цикле пока не пуст второй массив извлекаем из него первый путь, заходим в него и перебираем все элементы. Если файл добавляем в массив результатов(первый массив) если это каталог то полный путь до этого каталога добавляем во второй массив.

Вроде это должно работать.

dimagolov
1. масив массивов содержимого директорий
А зачем тут вложенные массивы?
 

dimagolov

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

FractalizeR

Новичок
С использованием того свойства PHP массивов, что их можно трактовать как стек, можно так сделать:

PHP:
<?php
function DirTraversalNoRecursion ($StartDir)
{
    //Хэндлы каталогов, к которым надо вернуться
	$dirHandles = array();
	
	//Имена каталогов, к которым надо вернуться
    $dirNames = array();
    
    //Храним имена файлов, которые мы обошли, если их надо вернуть из функции
    $filenames = array();
    
    //Открываем начальный каталог
    $currDirHandle = opendir($StartDir);
    if (! $currDirHandle) {
        die('Ошибка открытия корневого каталога для сканирования!');
    }
    $currDirName = $StartDir;
    
    //Перебираем все папки, начиная с корня
    while ($currDirHandle !== NULL) {
    	
    	//Читаем текущую папку
        while (($file = readdir($currDirHandle)) !== false) {
        	
        	//Пропускаем "." и ".." каталоги
        	if(is_dir($currDirName . '/' . $file) and $file[0]=='.') {
        		continue;
        	}
        	
        	//Если встретили папку - 
            if (is_dir($currDirName . '/' . $file)) {
            	
            	//запоминаем текущую в стеке
                array_push($dirHandles, $currDirHandle);
            	array_push($dirNames, $currDirName);
            	
            	//Переключаемся на сканирование встреченной папки
                $currDirHandle = opendir($currDirName . '/' . $file);
                $currDirName = $currDirName . '/' . $file;
                continue;
            }
            //Запоминаем имя файла для возврата
            $filenames[] = $currDirName . '/' . $file;
            
            //На всякий выводим на консоль
            echo($currDirName . '/' . $file."\r\n");
        }
        
        //Закрываем хэндл пройденного каталога
        closedir($currDirHandle);
        
        //Забираем из стека каталог, на котором мы остановились для продолжения обхода
        $currDirHandle = array_pop($dirHandles);
        $currDirName = array_pop($dirNames);
        
        //Продолжаем обход. array_pop вернет NULL, если для продолжения обхода больше нет каталогов        
    }
    
    //Возвращаем встреченные имена файлов
    return $filenames;
}
$filenames = DirTraversalNoRecursion('C:/Temp');
?>

Если речь идет не о курсовике, я бы glob воспользовался и не парился бы :)
 
Сверху