Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> прочитать вложенные директории 
:(
    Опции темы
murka
Дата 31.7.2006, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 6.12.2005
Где: Волгоград

Репутация: нет
Всего: 2



 smile Нужна помощь!
Читаю директорию и делаю определенные действия над каждым из её объектов. Вложенность неопределена, нужно просмотреть все файлы во всех папках. Запуталась! 
Как определять папка это или файл и читать директорию могу, а вот как идти дальше во вложенные директории и вернуться обратно - не пойму! 
Может кто чего подскажет! 
PM MAIL   Вверх
Nab
Дата 31.7.2006, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 8
Всего: 37



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


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
korob2001
Дата 31.7.2006, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Вот написал пример, без рекурсии и сторонних модулей. Подробности смотри в комнтариях.

Файл: scan.pl
Код

#!/usr/bin/perl
use strict;

# Получаем имя файла из массива @ARGV
my @dir_list = (shift);

# Если полученный файл существует и является каталогом, то:
if (-e $dir_list[0] and -d $dir_list[0]) {

    # Открываем файл, сюда будем сохранять имена всех вложенных файлов,
    # вместе с путями.
    open my $fh, ">", "all_files.txt" or die "Can't open file: $!\n";

    # Извлекаем первый елемент из массива на каждой итерации цикла
    # до тех пор, пока массив не будет пуст.
    while (my $dir = shift @dir_list) {

           # Открываем полученный каталог
           opendir(DIR, $dir) or die "Can't open directory '$dir': $!\n";

                   # Читаем каталог в цикле
                   while (my $file = readdir DIR) {

                          # Отбрасываем имена текущего и родительского каталогов
                          next if $file =~ /^\.\.?$/;

                          # Если это каталог, то:
                          if ( -d "$dir/$file" ) {
                                # добавляем его в массив @dir_list
                                unshift @dir_list, join("/", $dir, $file);
                          } else {
                                # в противном случае
                                print $fh "$dir/$file\n";
                          }
                   }

           # Закрываем текущий каталог
           closedir(DIR);

    }

    # Закрываем наш файл
    close($fh) or die "Can't close file: $!\n";
}

Запускаешь из командной строки, например вот так:
perl scan.pl C:/WINDOWS

Врезультате, в том же каталоге, где находится сам файл scan.pl будет создан текстовый файл all_file.txt, в котором будет сохранён список всех вложенных файлов в указанном каталоге, а также и вложенных каталогах.

ЗЫ: Код было бы не плохо ещё немного доработать, а так же сократить. Я специально использовал длиные записи, например вот это условие:
Код

# Если это каталог, то:
if ( -d "$dir/$file" ) {
    # добавляем его в массив @dir_list
    unshift @dir_list, join("/", $dir, $file);
} else {
    # в противном случае
    print $fh "$dir/$file\n";
}

можно было бы записать и вот так:
Код

(-d "$dir/$file") ? unshift @dir_list, join("/", $dir, $file) : print $fh "$dir/$file\n";

С другой стороны, в этом же условии записывать в файл, только в том случае, если он действительно является файлом, а не чем нить ещё. Потому else можно заменить на elsif(условие), если это конечно нужно. 

Это сообщение отредактировал(а) korob2001 - 31.7.2006, 17:26


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
korob2001
Дата 31.7.2006, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Вот аналогичный пример с рекурсией:
Код

#!/usr/bin/perl
use strict;

my $fh;
my @dir_list = (shift);

if (-e $dir_list[0] and -d $dir_list[0]) {
    open $fh, ">", "all_filez.txt" or die "Can't open file: $!\n";
    scan_dir(\@dir_list); # ВЫЗЫВАЕМ РЕКУРСИВНЫЙ МЕТОД (ПОДПРОГРАММУ)
    close($fh) or die "Can't close file: $!\n";
}

sub scan_dir {
    my $dir  = shift @{$_[0]} || return;
    opendir(DIR, $dir) or die "Can't open directory '$dir': $!\n";
    while (my $file = readdir DIR) {
       next if $file =~ /^\.\.?$/;
       (-d "$dir/$file") ? unshift(@{$_[0]},join("/",$dir,$file)) : print $fh "$dir/$file\n";
    }
    closedir(DIR);
    scan_dir($_[0]); # ВЫЗЫВАЕМ САМИ СЕБЯ
}

Программа намного меньше, но с примером без рекурсии можно сделать тоже самое. 


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Nab
Дата 31.7.2006, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 8
Всего: 37



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

А вот второй пример, мне не очень smile . От предыдущего оличается мало, хотя и использует рекурсию...
Я его немного переделаю...

Код

#!/usr/bin/perl    
use strict;    

scan_dir(shift); # ВЫЗЫВАЕМ РЕКУРСИВНЫЙ МЕТОД (ПОДПРОГРАММУ)    

sub scan_dir {    
    my $dir  = shift;    
    opendir(DIR, $dir) or die "Can't open directory '$dir': $!\n";    
    while (my $file = readdir DIR) {    
       next if $file =~ /^\.\.?$/; # пропускаем если двоеточие
       if (-d "$dir/$file") {
            scan_dir("$dir/$file") # если находим поддиректорию, то вызываем себя же, но для этого каталога.
        } else {
            print "$file\tin $dir\n"; # Вот здесь можем сделать что нибудь с файлом
        }    
    }    
    closedir(DIR);    
}

1;


В лучших традициях допишу smile
Вот эта конструкция:
Код

       if (-d "$dir/$file") {
            scan_dir("$dir/$file") # если находим поддиректорию, то вызываем себя же, но для этого каталога.
        } else {
            print "$file\tin $dir\n"; # Вот здесь можем сделать что нибудь с файлом
        }    

может быть заменена на :
Код

(-d "$dir/$file")?scan_dir("$dir/$file"):print "$file\tin $dir\n";

Но как по мне развернутая форма выигрывает в читабельности  smile   

Это сообщение отредактировал(а) Nab - 31.7.2006, 19:24


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
korob2001
Дата 1.8.2006, 01:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Цитата(Nab @  31.7.2006,  16:21 Найти цитируемый пост)
Но как по мне развернутая форма выигрывает в читабельности

Я не спорю, просто некоторые товарисчи предпочитают писать компактно, желательно вообще в одну строку.  smile 
 


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Nab
Дата 1.8.2006, 01:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 8
Всего: 37



Цитата(korob2001 @ 1.8.2006,  01:07)
Цитата(Nab @  31.7.2006,  16:21 Найти цитируемый пост)
Но как по мне развернутая форма выигрывает в читабельности

Я не спорю, просто некоторые товарисчи предпочитают писать компактно, желательно вообще в одну строку.  smile

Не спорю, но мы же не ПерлГольф играем, а помогаем народу понять как оно работает smile

А если у человека, в особенности у начинающего, вопрос, а он видит ТАКОЕ, что даже прочитать не может, то кому такая помощь нужна? И так все знают кто здесь модер smile

А те, кто предпочитают писать в одну строчку, обычно задают очень нетривиальные вопросы и знают чего хотят добиться в результате smile 


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
aksined
Дата 2.8.2006, 08:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 26.12.2005

Репутация: нет
Всего: 1



Если вы хотите помочь человеку с обработкой всех файлов, то хотя бы расскажите, как это сделать с помощью модуля, который входит в стандартную поставку. Ставить не надо, а использовать несложно.
Для вас написать несколько красивых решений - это одно. А человек потом все рвно вряд ли будет оформлять функции в виде модуля. Будет их копировать из скрипта в скрипт.
Код

use File::Find;
my $Dir = "с:/dir";
my @Subdir = qw(aaa bbb ccc);#новые подкаталоги добавлять сюда
find (\&search, map {"$DirCert/$_"} @Subdir);
#========================
sub search{
  my $name = $File::Find::name;
  if(-d $name){
    print "$name - это каталожица\n";
  }
  elsif(-f $name){
    print "$name - это файл\n";
  }
}


функция find получает список каталогов, ко всем элементам которых будут применена функция, переданная как первый параметр

#человек не написал, ему нужно САМОМУ научиться обходить дерево каталогов, или просто нужно обработать все файлы. Если второе, то не нужно писать так много кода
PM MAIL   Вверх
Nab
Дата 2.8.2006, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 8
Всего: 37



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


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
korob2001
Дата 2.8.2006, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 13
Всего: 61



Ну не знаю, я лично пытался помочь человеку с этим:
Цитата

а вот как идти дальше во вложенные директории и вернуться обратно - не пойму!

Не думаю, что здесь человек спрашивал о модуле File::Find, насколько я понял она хотела понять принцип того, как предвигаться по каталогам сверху вниз и в обратном направлении.
Да и я считаю, главное понять смысл, потому в первом примере каждая строка прокоментирована. А там глядишь, она напишет свой аналог File::Find, а может ещё чего-нить покруче, независимый от последнего.

ЗЫ: Гораздо надёжнее ездить на автомобиле, зная не то лько ПДД, но ещё и устройство автомобиля. Только не подумайте, что ярый противник CPAN, просто некоторые вещи я делаю вручную, точнее я стараюсь как можно меньше привязываться к какому-нить модулю.

Это сообщение отредактировал(а) korob2001 - 2.8.2006, 22:28


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
aksined
Дата 3.8.2006, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 26.12.2005

Репутация: нет
Всего: 1



Просьба не воспринимать мое сообщение как критику.
Вы готовы помочь - это главное. Причем в ситуациях, когда человек ленится почитать документацию или книгу (ко мне это тоже относится).
Я не сторонник и не протифник cpan.
Просто, мне кажется, что большей части людей, если и будет нужно понять, как произвести обход дерева(с рекурсией или без), потом все равно нужно будет использовать фунцию из модуля (своего или нет). Почему бы не рассказать о стандартных решениях.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: CGI программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к CGI программированию
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", качать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: разработка для Web | Следующая тема »


 




[ Время генерации скрипта: 0.0776 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.