Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 17.04.2024, 17:06
Аспирант
Отправить личное сообщение для firep91613 Посмотреть профиль Найти все сообщения от firep91613
 
Регистрация: 24.10.2023
Сообщений: 58

Работа с каталогами PHP
function printTree(int $level = 1) : void {
	$dir = opendir('.');

	if (!$dir) return;

	while (($file = readdir($dir)) !== false) {
		if ($file == '.' || $file == '..') continue;
		if (!is_dir($file)) continue;

		for ($i = 0; $i < $level; $i++) echo ' ';
		echo $file . PHP_EOL;

		if (!chdir($file)) continue;

		printTree($level + 1);
		chdir('..');
		flush();
	}

	closedir($dir);
}

// Структура каталогов:
main_catalog
   sub_catalog
      file1.php
      file2.php
   next_sub_folder

В $dir, при запуске функции - дескриптор main_catalog


Не понятно, что происходит, когда функция запрыгнет в sub_catalog и разшарит все файлы там. Директория будет закрыта, дальше управление перейдет во внешний вызов сюда: chdir('..') - выход наверх в main_catalog. Во внешнем вызове, на следующей итерции while в $file будет содержатся next_sub_folder.

Как связан chdir('..') и то что содержится в $file? Ну то есть в первом вызове readdir($dir) возвращает все содержимое main_catalog, потом, после выпрыгивания из sub_catalog, на следующей итерации while readdir($dir) возвращает следующую директорию. Не могу точно сформулировать, chdir('..') влияет на эту переменную $dir?
Ответить с цитированием
  #2 (permalink)  
Старый 17.04.2024, 20:29
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

function printTree(int $level = 1) : void {
    // открываем дескриптор текущей директории
    $dir = opendir('.');
 
    // завершаем работу функции, если не удалось открыть дескриптор
    if (!$dir) return;
 
    // перебираем элементы директории по её дескриптору
    while (($file = readdir($dir)) !== false) {
        // если это ссылка на текущую директорию или родительскую - игнорируем этот элемент
        if ($file == '.' || $file == '..') continue;
        // если это не директория - игнорируем этот элемент
        if (!is_dir($file)) continue;
 
        // выводим "отступ" от левого края
        for ($i = 0; $i < $level; $i++) echo ' ';
        // выводим название директории
        echo $file . PHP_EOL;
 
        // пытаемся изменить текущую директорию на дочернюю директорию $file
        // если не удалось - пропускаем директорию $file
        if (!chdir($file)) continue;
 
        // рекурсивно вызываем эту же функцию, чтобы она 
        // отобразила "дерево" каталогов, но уже для дочерней директории $file
        printTree($level + 1);
        // изменяем текущую директорию на изначальную
        chdir('..');
        // непонятно зачем, но пытаемся сбросить буфер вывода
        flush();
    }
 
    // закрываем дескриптор
    closedir($dir);
}
Ответить с цитированием
  #3 (permalink)  
Старый 18.04.2024, 12:36
Аспирант
Отправить личное сообщение для firep91613 Посмотреть профиль Найти все сообщения от firep91613
 
Регистрация: 24.10.2023
Сообщений: 58

Nexus,
это все так. Непонятно просто как под капотом работает. Когда будет выход из дочерней директории цикл во внешнем вызове после смены директории на изначальную запоминает на каком месте остановился? Видимо запоминает, без chdir('..') не работает.
Ответить с цитированием
  #4 (permalink)  
Старый 18.04.2024, 13:11
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

Сообщение от firep91613
Когда будет выход из дочерней директории цикл во внешнем вызове после смены директории на изначальную запоминает на каком месте остановился?
Да, запоминается, но это вовсе не заслуга chdir.
Дескриптор родительского каталога не закрывается до тех пор, пока все директории изначального каталога не будут перечислены.
Ответить с цитированием
  #5 (permalink)  
Старый 18.04.2024, 16:42
Аспирант
Отправить личное сообщение для firep91613 Посмотреть профиль Найти все сообщения от firep91613
 
Регистрация: 24.10.2023
Сообщений: 58

Сообщение от Nexus
Дескриптор родительского каталога не закрывается до тех пор, пока все директории изначального каталога не будут перечислены.
Ну да. Ну все равно, какая-то связь между откртым дескриптором и chdir есть. Без chdir просто не работает.
Ответить с цитированием
  #6 (permalink)  
Старый 18.04.2024, 19:25
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

Сообщение от firep91613
Ну все равно, какая-то связь между откртым дескриптором и chdir есть.
chdir - изменяет текущую директорию на указанную первым аргументом.
opendir - открывает дескриптор указанной первым аргументом директории.
Без chdir не работает, поскольку функция пытается получить исключительно дескриптор текущей директории (working directory).

Эту функцию можно переписать и без использования chdir, передавая функции printTree путь до каталога, дерево которого нужно вывести.

function printTree(string $path): void {
    $handle = opendir($path);
    if (!$handle) {
        return;
    }

    // and so on
}
Ответить с цитированием
  #7 (permalink)  
Старый 19.04.2024, 12:45
Аспирант
Отправить личное сообщение для firep91613 Посмотреть профиль Найти все сообщения от firep91613
 
Регистрация: 24.10.2023
Сообщений: 58

Nexus,
понятно, спасибо.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Почему в JavaScript не изменили простую и очевидную штуку? jaroslav.tavgen Общие вопросы Javascript 39 21.04.2020 19:48
Работа с регулярными выражениями в php raja Серверные языки и технологии 2 30.10.2017 15:27
Работа php скриптов с xml файлом guru_nemo Общие вопросы Javascript 9 02.10.2015 15:20
Работа с PHP Minify tyhur Серверные языки и технологии 2 13.06.2013 10:56
Работа php с запросами. Duda.Ml1986@gmail.com Серверные языки и технологии 16 07.01.2012 16:04