Forum Webscript.Ru

Программирование => Perl => Тема начата: Dart Sidius от 29 Июля 2004, 20:34:35

Название: Создание дерева каталогов
Отправлено: Dart Sidius от 29 Июля 2004, 20:34:35
Как енто можно сделать не прибегая ник каким модулям, т.е. ручками. Есть корневой каталог. А из него куча ещё...вот их надо все пройти...
Название: Создание дерева каталогов
Отправлено: Billi от 29 Июля 2004, 21:00:50
Приблезительно вот так :)

&dir(".","\\t");
sub dir($,$){
 my $DIR;
 my $shift=$_[1];
 my $dirr_=$_[0];
 opendir($DIR,$dirr_);
 print "$shift [$dirr_]\\n";
 foreach(readdir($DIR)){
  if((-d $_)&&($_ ne \'.\')&&($_ ne \'..\')){&dir($_,"$shift\\t");}
  elsif(($_ ne \'.\')&&($_ ne \'..\')){print "$shift $_\\n";}
 }
 closedir(DIR);
}
Название: Создание дерева каталогов
Отправлено: NeoNox от 29 Июля 2004, 23:18:43
Dart Sidius
perldoc File::Find
Billi
с софтлинками этот код пробовал?
Название: Создание дерева каталогов
Отправлено: Billi от 30 Июля 2004, 13:40:43
to NeoNox
 софтлинками ?? если не затруднит, что это?
Название: Создание дерева каталогов
Отправлено: NeoNox от 30 Июля 2004, 14:02:30
man ln
проблема в том, что твой скрипт может "убежать" из текущей папки или зациклиться.
Название: Создание дерева каталогов
Отправлено: Billi от 30 Июля 2004, 14:44:41
Пробовать не пробовал, но это вполне возможно (при первой же возможноти попробую)
для верности можно поменять условие
if((-d $_)&&(! -l $_)&&($_ ne \'.\')&&($_ ne \'..\')){&dir($_,"$shift\\t");}
точно должно работать
Название: Создание дерева каталогов
Отправлено: y0sh1 от 26 Августа 2004, 11:15:47
Помогите ламерку... похожего топа не нашёл решил сюда запостить...
Проблема: надо написать скрипт на перле, который:
- в данной директории показывает список папок в ней (только в ней - во влженных не надо) и их размер (соответственно с подпапками считать);
- показывал бы тоже самое, но только размер файлов (во всей папке с подпапками) считал бы не для всех файлов, а только по заданной маски - например выдать размер всех файлов *.doc каждой подпапки в данной папке.
Сам в перле начинающий... надыбал скрипт на форуме, видоизменил (пока только для 1-го случая) - но что-то не пашет:

Код:
#! perl -w
use strict;
sub dir_ls {
        my $save_dir;
        my $root = shift;
        local *DIR_LS;
 
        opendir DIR_LS ,$root;
 
        while (my $file = readdir (DIR_LS) ) {
               next if $file =~ /^\\.\\.?$/;
               print "$root/$file\\n";
               if (-d "$root/$file") {
                   $count_d++;
                   dir_ls ("$root/$file");
               } else {
                   $dir_size += (stat("$root/$file"))[7];
                   $count_f++;
print "$count_f";
               }
        }
print "\\n\\nTotal -\\nDirs: $count_d\\nFiles: $count_f\\nSize: $dir_size\\n";
}
 
opendir FDIR, ".";
while($nm = readdir FDIR){
next if ($nm eq ".");
next if ($nm eq "..");
 
$stat     = 0;
$count_f  = 0;
$count_d  = 0;
$dir_size = 0;
     dir_ls ($nm);  
}
closedir FDIR;


типа пишет : "Global symbol "$count_d" requires explicit package name" для всех переменных - что не так!? Заранее спасибо, если кто поможет.... ну а если посоветуют ещё и конструкцию  для 2-го варианта (чтобы размер файлов по маске считал0 - то будет вообще счастье! Зараенее спасибо!
Название: Создание дерева каталогов
Отправлено: AnnA от 26 Августа 2004, 11:36:59
y0sh1, Вам надо малость подправить вот этот вот участочек:$stat = 0;
$count_f = 0;
$count_d = 0;
$dir_size = 0;

вот на такой хотя бы:my ($stat,$count_f,$count_d,$dir_size)=(0,0,0,0);
Название: Создание дерева каталогов
Отправлено: y0sh1 от 26 Августа 2004, 13:48:23
Ну вот исправил...

Код:
use strict;
 
my $s_root   = \'\';
my $dir_size = 0;
my $t_dir_size = 0;
 
sub dir_ls {
        my $save_dir;
        my $root = shift;
        local *DIR_LS;
 
        opendir DIR_LS ,$root;
 
        while (my $file = readdir (DIR_LS) ) {
               next if $file =~ /^\\.\\.?$/;
               print "$root/$file\\n";
               if (-d "$root/$file") {
                   dir_ls ("$root/$file");
               } else {
                   $dir_size += (stat("$root/$file"))[7];
               }
        }
print "$dir_size\\n";
$t_dir_size += $dir_size;
$dir_size = 0;
}
opendir(D,\'e:/111\');
while($s_root=readdir(D))
{
dir_ls ($s_root);
print "\\nSize of $s_root: $t_dir_size\\n";
}
closedir(D);


только он почему то выводит не директорию e:/111 , а корневую!? Где ошибка!?
Название: Создание дерева каталогов
Отправлено: AnnA от 26 Августа 2004, 14:54:29
это Вы вызываете скрипт браузером в "винде"?
тогда Вам надо пользоваться Win32API::File
посудите сами - ну откуда Вашему Apache известно что такое e:/111. :)
Цитировать
Dart Sidius:
Есть корневой каталог. А из него куча ещё...вот их надо все пройти...

Цитировать
y0sh1:
только он почему то выводит не директорию e:/111 , а корневую!?
Название: Создание дерева каталогов
Отправлено: y0sh1 от 26 Августа 2004, 15:00:06
AnnA
Сорри, я толькотнедавно засел за перл... апапч мне не нужен... он и не установлен даже.... ставил активперл под винду... пытаюсь скриптом сделать работу с директорией вот и всё ... и не получается.. :(
Название: Создание дерева каталогов
Отправлено: NeoNox от 26 Августа 2004, 15:37:33
вот здесь
sub dir_ls {
        my $save_dir;
        my $root = shift;
        local *DIR_LS;
вставь
print "Я здесь: $root\\n";
и увидишь где твой скрипт на данный момент.
Название: Создание дерева каталогов
Отправлено: Phoinix от 26 Августа 2004, 15:46:24
AnnA
Цитировать
посудите сами - ну откуда Вашему Apache известно что такое e:/111


Собственно Perl никогда у Apache не спрашивает, зает ли он такую директорию или нет... :)

При работе Perl скрипта Apache получает только результат работы...

y0sh1

sub dir_ls {
        my $save_dir;
        my $root = shift;
        local *DIR_LS;
 
        opendir DIR_LS ,$root; #!!!!!


$root в твоем скрипте - название папки которая находится в e:/111, но никак не путь к этой папке, естественно, что opendir будет открывать не ту директорию которую надо, а пытаться открыть директорию $root находящуюся в корне (как правило диск на котором установлен Perl)...

Указывай при использовании функции opendir полный путь, и тогда все будет нормально... ;)
Название: Создание дерева каталогов
Отправлено: y0sh1 от 26 Августа 2004, 16:04:48
NeoNox
Цитировать
вставь print "Я здесь: $root\\n"; и увидишь где твой скрипт на данный момент.

вставил... всё равно не понятно, почему проход начинается с корневой директории (из которой запускается скрипт), а не из папки "E:/111"!?
Те почему то не получается передать в рекурсив функцию путь... она идёт из корня... :(
Вот тут посоветовали применить конструкцию вида:
Цитировать
$dir_name="e:\\\\111";
chdir($dir_name);
opendir(D,$dir_name);

!?!? :(
Название: Создание дерева каталогов
Отправлено: y0sh1 от 26 Августа 2004, 16:30:23
Во... нашёл.. точнее мне показали...
Цитировать
       while (my $file = readdir (DIR_LS) ) {
               next if $file =~ /^\\.\\.?$/;
              next if $root =~ /^\\.\\.?$/;
               print "file: $root/$file\\n";
               if (-d "$root/$file")
               {
                   dir_ls ("$root/$file");

Вот с этой строчкой (выделенной) всё вроде заработало... только почему... что-то я совсем не втыкаю... :(
Название: Создание дерева каталогов
Отправлено: y0sh1 от 26 Августа 2004, 16:32:33
Phoinix
Цитировать
Phoinix:
Указывай при использовании функции opendir полный путь, и тогда все будет нормально...

спасибо что ткнул... только мне надо не то что бы указать, а передать этот путь в функцию... и что-то не очень получалось...
Название: Создание дерева каталогов
Отправлено: Phoinix от 26 Августа 2004, 19:02:19
y0sh1
Цитировать
только почему... что-то я совсем не втыкаю


Функция readdir возвращает массив в котором первые два элемента являются \'.\' и \'..\'

попробуй набрать в консоли cd .. и и сразу поймешь, почему директория: e:/111/.. является директорией e:/

А эта строка просто, напросто проверяет соответсвие переменной -> .. и при наличии таковой делает следующий цикл...

Вообще проверять Regexp каждый элемент массива - непрактично, проще перед циклом просто напросто два раза повторить readdir:

readdir DIR_LS; readdir DIR_LS;
while (my $file = readdir (DIR_LS) ) {
#next if $file =~ /^\\.\\.?$/;
Название: Создание дерева каталогов
Отправлено: NeoNox от 26 Августа 2004, 19:19:23
Цитировать
Phoinix:
Вообще проверять Regexp каждый элемент массива - непрактично, проще перед циклом просто напросто два раза повторить readdir:

Это что-то новенькое. Зачем??
Название: Создание дерева каталогов
Отправлено: y0sh1 от 26 Августа 2004, 19:40:26
Вобщем после дня эксперементов наваял я довольно простенький (и наверно всё же кривоватый) скрипт:

use strict;

my $s_root   = \'\';
my $dir_size = 0;
my $file_size = 0;
my $t_dir_size = 0;
my $dir_name = \'\';

sub dir_ls {
        my $save_dir;
        my $root = shift;
        local *DIR_LS;

        opendir DIR_LS ,$root;

        while (my $file = readdir (DIR_LS) ) {
next if $file =~ /^\\.\\.?$/;
next if $root =~ /^\\.\\.?$/;
               if (-d "$root/$file") {
                   dir_ls ("$root/$file");
               } else {
                   $dir_size += (stat("$root/$file"))[7];
               }
        }
#print "$s_root : $dir_size\\n";
}
$dir_name="e:\\\\111";
chdir($dir_name);
opendir(D,$dir_name);
while($s_root=readdir(D)) {
if (-d "$s_root") {
dir_ls ($s_root);
print "$s_root : $dir_size\\n";
$t_dir_size += $dir_size;
}
else {
$file_size += (stat("$s_root"))[7];
}
$dir_size = 0;
}
closedir(D);
print "Files in root directory: $file_size\\n";
$t_dir_size += $file_size;
print "\\nTotal: $t_dir_size\\n";

Он проходит по заданной папке и выводит объём всех подпапок + отдельно объём файлов в корне указаной папки... Теперь решил прикрутить помимо подсчёта объёма всей подпапки ещё и объём файлов в ней по маске - например *.mp3 - по предложеной на форуме кнструкции:
my $size = 0;
$size += (stat($_))[7] for (glob(\'e:/111/*.mp3\'));
print "Size *.mp3 - $size bite";

Соответственно в скрипт написанный выше добавил:


................
               } else {
                   $dir_size += (stat("$root/$file"))[7];
[b]$dir_size_mp3 += (stat("$root/$file"))[7] for (glob("$root/$file/*.mp3"));[/b]
               }
        }
#print "$s_root : $dir_size\\n";
}

...............

[b]print "MP3 in: $dir_size_mp3\\n\\n";[/b]


Но что-то не катит... просто записывает в $dir_size_mp3 какое-то число... !?!?!? В чём может быть дело!?


Phoinix
Цитировать
Phoinix:
Вообще проверять Regexp каждый элемент массива - непрактично, проще перед циклом просто напросто два раза повторить readdir:

 readdir DIR_LS; readdir DIR_LS; while (my $file = readdir (DIR_LS) ) { #next if $file =~ /^..?$/;

проще действительно... у меня не пошло..... может дело в том, что функция рекурсивно вызывется!?
Название: Создание дерева каталогов
Отправлено: Phoinix от 26 Августа 2004, 20:42:59
NeoNox
Цитировать
Это что-то новенькое. Зачем??


Вообщем я чаще readdir закидываю в массив, упераю первых два элемента, а потом провожу обработку...

В принципе, палка о двух концах:

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

Цитировать
у меня не пошло..... может дело в том, что функция рекурсивно вызывется!


Что не пошло???

Цитировать
Но что-то не катит... просто записывает в $dir_size_mp3 какое-то число... !?!?!? В чём может быть дело!?


А ты что картинку ожидал увидеть???

[OFF]Может все-таки книжку почитать?[/OFF]
Название: Создание дерева каталогов
Отправлено: y0sh1 от 27 Августа 2004, 10:20:48
Phoinix
Может все-таки книжку почитать?[/quote]
да я знаю, что ламер в перле... читаю конечно... скрипт вроде подправил...