Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Листинг каталога
 
 автор: denvor   (24.01.2005 в 00:26)   письмо автору
 
 

Доброго времени суток всем!
Подскажите, плиз, как проще всего получить листинг каталога со всеми вложенными каталогами и файлами+размер и время создания+ записать в текстовый файл.
В книге подробно описано получение списка файлов в директории. А как организовать обход дерева?

   
 
 автор: glsv (Дизайнер)   (24.01.2005 в 00:33)   письмо автору
 
   для: denvor   (24.01.2005 в 00:26)
 

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

   
 
 автор: cheops   (24.01.2005 в 00:40)   письмо автору
 
   для: denvor   (24.01.2005 в 00:26)
 

Обычно для этого используется рекурсивная функция обхода... вообще когда имеется дерево - следует использовать рекурсивный спуск - это единственная задача где по настоящему нужна рекурсия.
Попробуйте запусить скрипт (только не в корне диска С :)))
<?php
  scan_dir
(".");
  
//////////////////////////////////////////////////////////
  // Рекурсивная функция - спускаемся вниз по каталогу
  //////////////////////////////////////////////////////////
  
function scan_dir($dirname)
  {
    
// Открываем текущую директорию
    
$dir opendir($dirname);
    
// Читаем в цикле директорию
    
while (($file readdir($dir)) !== false)
    {
      
// Если файл обрабатываем его содержимое
      
if($file != "." && $file != "..")
      {
        
// Если имеем дело с файлом - регистрируем его
        
if(is_file($dirname."/".$file))
        {
          echo 
$dirname."/".$file." - ".
               
date("m.d.y",filemtime($dirname."/".$file))." - ".
               
filesize($dirname."/".$file)."<br>";
        }
        
// Если перед нами директория, вызываем рекурсивно
        // функцию scan_dir
        
if(is_dir($dirname."/".$file))
        {
          echo 
$dirname."/".$file."<br>";
          
scan_dir($dirname."/".$file,$fd,$fb);
        }
      }
    }
    
// Закрываем директорию
    
closedir($dir);
  }
?>

   
 
 автор: denvor   (24.01.2005 в 13:36)   письмо автору
 
   для: cheops   (24.01.2005 в 00:40)
 

Волшебство! Оно работает!
Правда, я попробовал в файл записать:

// создаем пустой файл  для записи
      $file = fopen("check_new.txt", "w+");
...
...
 $str = $dirname."/".$file." - ". date("m.d.y",filemtime($dirname."/".$file))." - ".filesize($dirname."/".$file);
 fputs ($file, $str); 

Файл создается, но в него ничего не пишется:
Warning: fputs(): supplied argument is not a valid stream resource in w:\home\127.0.0.1\www\list1.php on line 31
Что не так?

   
 
 автор: glsv (Дизайнер)   (24.01.2005 в 14:48)   письмо автору
 
   для: denvor   (24.01.2005 в 13:36)
 

Похоже пустой идентификатор файла $file.
Вы уверены, что он нигде не затирается в коде?

   
 
 автор: denvor   (24.01.2005 в 17:05)   письмо автору
 
   для: glsv (Дизайнер)   (24.01.2005 в 14:48)
 

Точно, перезаписывается, но... Поменял на $file1 - то же самое. Чтобы не гадать - вот весь код (это код cheops'a в модификации для записи в файл):

<?php 
       $file1 
fopen("check_new.txt""w+");  //создаем файл
   
scan_dir("."); 
  
////////////////////////////////////////////////////////// 
  // Рекурсивная функция - спускаемся вниз по каталогу 
  ////////////////////////////////////////////////////////// 
  
function scan_dir($dirname
  { 
    
// Открываем текущую директорию 
    
$dir opendir($dirname); 
    
// Читаем в цикле директорию 
    
while (($file readdir($dir)) !== false
    { 
      
// Если файл обрабатываем его содержимое 
      
if($file != "." && $file != ".."
      { 
        
// Если имеем дело с файлом - регистрируем его 
        
if(is_file($dirname."/".$file)) 
        { 
          
$str $dirname."/".$file." - "date("m.d.y",filemtime($dirname."/".$file))." - ".filesize($dirname."/".$file);
         
fputs ($file1$str);          //пишем в файл 
        

        
// Если перед нами директория, вызываем рекурсивно 
        // функцию scan_dir 
        
if(is_dir($dirname."/".$file)) 
        { 
          
$str  $dirname."/".$file;
          
fputs ($file1$str);             //снова пишем в файл 
          
scan_dir($dirname."/".$file,$fd,$fb); 
        } 
      } 
    } 
    
// Закрываем директорию 
    
closedir($dir); 
  } 

fclose ($file1);                 //закрываем файл
?> 

   
 
 автор: denvor   (24.01.2005 в 18:10)   письмо автору
 
   для: denvor   (24.01.2005 в 17:05)
 

Немного переделал - теперь файл для записи открывается непосредственно перед записью. Все заработало. Теперь появилиь такие вопросы:
- как вставить перенос на новую строку
- это наверное, неправильно открывать файл в цикле, не будет ли это медленно работать?
- в связи с этим: как писать эти данные в массив с тем, чтобы потом один раз записать массив в файл?

   
 
 автор: cheops (из ННГУ)   (24.01.2005 в 18:36)
 
   для: denvor   (24.01.2005 в 18:10)
 

1) Для перевода строки следует добавить последовательность \n
<?php
  
echo ""Слово\n";
?>

2) Да, так делать не стоит в предыдущем листинге следует просто передать дескриптор открытого файла $file1 в качестве параметра функции.
3) Массив следует объявить в функции с атрибутом GLOBAL
<?php
GLOBAL $arr;
$arr = array();
?>

В этом случае результаты будут сохранятся после выхода из функции. Массив для удобства лучше упаковать в строку как это описывается по ссылке

http://www.softtime.ru/forum/read.php?id_forum=1&id_theme=907

   
 
 автор: denvor   (07.02.2005 в 23:16)   письмо автору
 
   для: cheops (из ННГУ)   (24.01.2005 в 18:36)
 

"...передать дескриптор открытого файла $file1 в качестве параметра функции."
это вот так?

function scan_dir($dirname, $file1)

   
 
 автор: cheops   (08.02.2005 в 00:09)   письмо автору
 
   для: denvor   (07.02.2005 в 23:16)
 

да.

   
 
 автор: denvor   (07.02.2005 в 23:18)   письмо автору
 
   для: cheops (из ННГУ)   (24.01.2005 в 18:36)
 

И сразу еще вопрос: полученный листинг нужно сравнить с предыдущем - как это правильнее сделать сравнивать массивы или файлы?

   
 
 автор: isset   (07.02.2005 в 23:26)   письмо автору
 
   для: denvor   (07.02.2005 в 23:18)
 

Если версия PHP >= 4.3.0, то можно использовать для получения листинга следующий скрипт:

<?php 
echo "<pre>";
print_r(glob("/home/myfiles/*.*"));
?>

Кроме того можно использовать:

<?php
echo "<pre>";
print_r(glob("/home/myfiles/*/*.{php,txt}"GLOB_BRACE));
?>

Это выведет все файлы с расширением php или txt из /home/myfiles/ и из папок которые находятся в /home/myfiles/.

   
 
 автор: denvor   (08.02.2005 в 00:24)   письмо автору
 
   для: isset   (07.02.2005 в 23:26)
 

Здорово!
А как прикрутить туда вывод размера и даты изменения файла? В справочнике на сайте я не нашел эту функцию :(

   
 
 автор: cheops   (08.02.2005 в 00:31)   письмо автору
 
   для: denvor   (08.02.2005 в 00:24)
 

Для определения размера файла предназначена функция filesize(), принимающая в качестве единственного параметра путь к файлу и возвращает размер файла в байтах. http://www.softtime.ru/dic/id_dic=184&id_group=6
Для определения даты последнего изменения файла, предназначена функция filectime() http://www.softtime.ru/dic/id_dic=178&id_group=6

   
 
 автор: denvor   (08.02.2005 в 21:10)   письмо автору
 
   для: cheops   (08.02.2005 в 00:31)
 

2 cheops: с кодом isset все получилось - прогнал массив, прикручивая к файлам время и дату и запихивая обратно в массив. Но! Все равно нужно делать рекурсивный обход дерева - так что ваш код для моих целей больше подходит. Я попробовал в ваш код вставить вместо вывода листинга на экран вывод его в массив, с тем, чтобы за пределами функции дальше работать с эти массивом, но ниего не вышло - за пределы функции массив не передается даже при объявлении GLOBAL (global ... я вставил сразу после первой фигурной скобки).

   
 
 автор: cheops   (08.02.2005 в 22:56)   письмо автору
 
   для: denvor   (08.02.2005 в 21:10)
 

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

   
 
 автор: denvor   (10.02.2005 в 00:44)   письмо автору
 
   для: cheops   (08.02.2005 в 22:56)
 

Доброго времени суток, cheops и All!
Вот код:
как сделать правильно и в чем проблема -не знаю. Если ставлю echo $arr[2]; перед последней фигурной скобкой - выводит значение, а после функции - нет :(

<?php 
  
  scan_dir
("."); 
   function 
scan_dir($dirname
   { 
   GLOBAL 
$arr
   
$arr = array();
            
// Открываем текущую директорию  
            
$dir opendir($dirname);
    
// Читаем в цикле директорию 
    
while (($file readdir($dir)) !== false
    { 
      
// Если файл обрабатываем его содержимое 
      
if($file != "." && $file != ".."
      { 
        
// Если имеем дело с файлом - регистрируем его 
        
if(is_file($dirname."/".$file)) 
        { 
          
$arr[] = $dirname."/".$file." - ".date("m.d.y",filemtime($dirname."/".$file))." - ".filesize($dirname."/".$file)."<br>"
         
         } 
        
// Если перед нами директория, вызываем рекурсивно 
        // функцию scan_dir 
        
if(is_dir($dirname."/".$file)) 
        { 
          
$arr[] = $dirname."/".$file."<br>"
          
scan_dir($dirname."/".$file,$fd,$fb); 
        } 
      } 
    } 
    
// Закрываем директорию 
    
closedir($dir); 

  } 
// посмотрим третий элемент массива, к примеру...
echo ($arr[2]);

?> 

   
 
 автор: cheops   (10.02.2005 в 09:49)   письмо автору
 
   для: denvor   (10.02.2005 в 00:44)
 

Хм... а уменя такой вариант всё выводит... какая версия PHP?

   
 
 автор: denvor   (10.02.2005 в 14:19)   письмо автору
 
   для: cheops   (10.02.2005 в 09:49)
 

Да, действительно работает. Теперь я после последней фигурной скобки вставляю

foreach($arr as $val)
   {
      echo("$val");
   }

Выводит только файлы (без директорий) в текущей директории и ошибку:
Undefined variable: fb in w:\home\127.0.0.1\www\list2.php on line 27
Вот.

   
 
 автор: cheops   (10.02.2005 в 22:46)   письмо автору
 
   для: denvor   (10.02.2005 в 14:19)
 

Хм... дело в том, что здесь происходит рекурсивный вызов и если изменяется число параметров в исходной функции - нужно изменить число и в вызове (я гляжу это забы сделать :), поэтому исправьте пожалуйста строку
<?php
scan_dir
($dirname."/".$file,$fd,$fb);
?>

на
<?php
scan_dir
($dirname."/".$file);
?>

   
 
 автор: denvor   (11.02.2005 в 17:07)   письмо автору
 
   для: cheops   (10.02.2005 в 22:46)
 

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

   
 
 автор: denvor   (14.02.2005 в 18:31)   письмо автору
 
   для: denvor   (11.02.2005 в 17:07)
 

Отвечаю сам себе :):
Явно определяя переменную $arr как массив, мы обнуляем ее каждый раз при рекурсивном обращении. Убираем строчку $arr = array (); - все работает.
Всем большое спасибо!

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования