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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Рекурсивный обход каталога и вывод в виде tree 
:(
    Опции темы
dimdiden
Дата 23.1.2015, 10:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Привет всем!

Светлые умы, помогите пожалуйста с алгоритмом действия по такому заданию:

Необходимо написать программу которая выведет от заданной директории все файлы и поддиректории в псевдографическом виде. Как в утилите tree:
.
├── config.dat
├── data
│   ├── data1.bin
│   ├── data2.sql
│   └── data3.inf
├── images
│   ├── background.jpg
│   ├── icon.gif
│   └── logo.jpg
├── program.exe
└── readme.txt 

Условия: не пользоваться модулями.

Описание:

Вот с этого сайта понял как делать рекурсивный обход директории http://perlmaven.com/recursive-subroutines

use strict;
use warnings;
use 5.010;
 
my $path = shift || '.';
 
traverse($path);
 
sub traverse {
    my ($thing) = @_;
    
    say $thing;
    return if not -d $thing;
    opendir my $dh, $thing or die;
    while (my $sub = readdir $dh) {
        next if $sub eq '.' or $sub eq '..';
 
        traverse("$thing/$sub");
    }
    close $dh;
    return;
}

Т.е. просто перечень всех файлов и поддиректорий я вывожу.
Но натолкните пожалуйста на мысль, как организовать вот эти вот "сдвиги вправо" древовидно по каждой субдиректории как в команде tree?
У меня была мысль каким то образом сделать "хэш хэшей" где ключ - поддиректория а значение - уровень вложенности.
Но думаю это довольно сложно, есть путь и попроще.

Заранее спасибо!


PM MAIL   Вверх
alezzz
Дата 23.1.2015, 14:45 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


сплю...
**


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

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



передавай уровень в функцию, например  traverse("$thing/$sub", ++$level);

это универсально, а в данном случае кажется можно и слеши посчитать в пути.

Добавлено через 13 минут и 46 секунд
с ++$level в функции это я погорячился, проверил на вашем примере, сильно сдвигает, лучше сделать $level++ перед while

Это сообщение отредактировал(а) alezzz - 23.1.2015, 14:49
PM MAIL   Вверх
dimdiden
Дата 23.1.2015, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(alezzz @  23.1.2015,  14:45 Найти цитируемый пост)
 traverse("$thing/$sub", ++$level)


Вот это мы должны передавать когда наш $thing/$sub является директорией. Но счетчик $level будет плюсоваться при каждой встрече директории, даже если это второй уровень вложенности - если субдиректорий было много, счетчик уже не будет со значением 2.

Я понимаю, Вы сказали в общем, принцип действия. Но я нубоват, если можно чуток бы по подробнее. Спасибо.

PM MAIL   Вверх
alezzz
Дата 23.1.2015, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


сплю...
**


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

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



Я ж потом добавил что инкремент при передаче в функцию неправильно делать. Делайте $level++ например после say и передавайте traverse("$thing/$sub", $level)
PM MAIL   Вверх
dimdiden
Дата 23.1.2015, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(alezzz @  23.1.2015,  17:24 Найти цитируемый пост)
Я ж потом добавил


Не увидел, сори.
PM MAIL   Вверх
dimdiden
Дата 24.1.2015, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Покрутил немного с советом что был дан выше
Теперь код имеет вид:
Код

#!/usr/bin/perl
use strict;
use warnings;
use feature qw(say);
my $level = 0;
my $ref_lev = \$level;

sub reeed {
    my ( $thing, $level ) = @_; 
    ( my $name = $thing ) =~ s/.*\///s;
    print '+', '-' x $level, "$name", "\n";
    $level = $level + 4;
    return if not -d $thing;
    opendir my $dh, $thing or die;
    while (my $sub = readdir $dh) {
        next if $sub eq '.' or $sub eq '..';
        reeed ( "$thing/$sub", $level );
            
    }   
}
reeed ( $ARGV[0], $$ref_lev );


Выхлоп в таком виде:
+
+----efi
+--------EFI
+------------redhat
+----------------grub.efi
+----vmlinuz-2.6.32-431.el6.x86_64
+----initramfs-2.6.32-431.el6.x86_64.img
+----.vmlinuz-2.6.32-431.el6.x86_64.hmac
+----grub
+--------device.map
+--------menu.lst
+--------jfs_stage1_5
+--------reiserfs_stage1_5
+----config-2.6.32-431.el6.x86_64
+----System.map-2.6.32-431.el6.x86_64

Необходимо дальше решать задачу:
1. Из за цикла while читается поочередно каждый элемент. Естественно, из за этого файлы которые находятся в корне директории могут идти вразнобой с субдиректориями, что видно выше. Наверное надо все элементы загонять в массив или хэш и там уже как то сортировать?
2. Куда копать, что бы графическое предствление (+---) содержимого субдиректории начиналось с сасмой субдиректории?

Спасибо!
PM MAIL   Вверх
alezzz
Дата 26.1.2015, 08:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


сплю...
**


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

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



По п.1 можно и загуглить:
http://stackoverflow.com/questions/1679304...eaddir-in-order
PM MAIL   Вверх
dimdiden
Дата 27.2.2015, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Привет всем опять!
Пока что дошел вот до такого уровня:
Код

#!/usr/bin/perl
use strict;
use warnings;

my $start_level = 0;
my $src = $ARGV[0];

print "$ARGV[0]\n";
my @arr = sort_ ($ARGV[0], $start_level);

sub sort_ {
    my ($src, $level) = @_; 
    opendir (my $dh, $src);
    my @sort_dir = grep {!/^\.{1,2}$/} map $_->[0], sort {$a->[1] <=> $b->[1] || $a->[0]cmp $b->[0] } map [ $_, -f "$src/$_"], readdir ($dh); #здесь убираются файлы . и .. и происходит сортировка
    closedir ($dh);
    foreach my $elem (@sort_dir) {
        if ( -d "$src/$elem" ) { 
            printf "%s|- %-10s\n", '|   ' x $level, $elem;
            sort_ ("$src/$elem", ++$level); # если элемент - папка, вызываем рекурсию по новой, добавляем счетчик уровней вложености
            $level = $level -1; # и сразу убавляем, для следующих элементов
        } else {
            printf "%s|- %-10s\n", '|   ' x $level, $elem;
          }   
    }   
}


Вывод такого плана:
Код

/boot/
|- efi       
|   |- EFI       
|   |   |- redhat    
|   |   |   |- grub.efi  
|- grub      
|   |- device.map
|   |- e2fs_stage1_5
|   |- fat_stage1_5
|   |- ffs_stage1_5
|   |- grub.conf 
|   |- iso9660_stage1_5
|   |- jfs_stage1_5
|   |- menu.lst  
|   |- minix_stage1_5
|   |- reiserfs_stage1_5
|   |- splash.xpm.gz
|   |- stage1    
|   |- stage2    
|   |- ufs2_stage1_5
|   |- vstafs_stage1_5
|   |- xfs_stage1_5
|- lost+found
|- .vmlinuz-2.6.32-431.el6.x86_64.hmac
|- System.map-2.6.32-431.el6.x86_64
|- config-2.6.32-431.el6.x86_64
|- initramfs-2.6.32-431.el6.x86_64.img
|- symvers-2.6.32-431.el6.x86_64.gz
|- vmlinuz-2.6.32-431.el6.x86_64


А надо, естественно, что бы вот так было:

Код

|- efi       
|    |- EFI       
|         |- redhat    
|             |- grub.efi


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


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

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


 




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


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

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