2015-07-09 3 views
2

Я пытаюсь построить такую ​​структуру.Как построить иерархический хеш в Perl из дерева каталогов

{ 
    "file1": "supersong.mp3", 
    "file2": "supersong2.mp3", 
    "file3": "text.txt", 
    "file4": "tex2t.txt", 
    "file5": "text3.txt", 
    "file6": "json.pl", 
    "directory_movies": [ 
     "file1": "supersong.mp3", 
     "file2": "supersong2.mp3", 
     "file3": "text.txt", 
     "file4": "tex2t.txt", 
     "file5": "text3.txt", 
     "file6": "json.pl", 
     "directory_sub_movies": [ 
      "file1": "supersong.mp3", 
      "file2": "supersong2.mp3", 
      "file3": "text.txt", 
      "file4": "tex2t.txt", 
      "file5": "text3.txt", 
      "file6": "json.pl", 
    ] 

] };

Как и любая иерархия каталогов в моем случае в unix. Таким образом, у нас есть простые файлы или каталоги, если это каталог, это вложенный хеш и т. Д. Рекурсивно.
Мне нужно представить его как хэш в perl, самый простой способ, который я нашел, - использовать модуль File::Find.
Он работает правильно, но я не могу понять, как сохранить иерархию в хеше, чтобы быть вложенной, как указано выше.
Вот мой тестовый скрипт. Это правильно определяет тип текущего элемента.

sub path_checker { 
    if (-d $File::Find::name) { 
     print "Directory " . $_ . "\n"; 
    } 
    elsif (-f $File::Find::name) { 
     print "File " . $_ . " Category is " . basename($File::Find::dir) . "\n"; 
    } 

} 
sub parse_tree { 
    my ($class,$root_path) = @_; 
    File::Find::find(\&path_checker, $root_path); 
} 

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

ответ

3

подпапки также должны быть хэш, а не массивы,

use strict; 
use warnings; 

# use Data::Dumper; 
use File::Find; 
use JSON; 

sub parse_tree { 
    my ($root_path) = @_; 

    my %root; 
    my %dl; 
    my %count; 

    my $path_checker = sub { 
     my $name = $File::Find::name; 
     if (-d $name) { 
     my $r = \%root; 
     my $tmp = $name; 
     $tmp =~ s|^\Q$root_path\E/?||; 
     $r = $r->{$_} ||= {} for split m|/|, $tmp; #/ 
     $dl{$name} ||= $r; 
     } 
     elsif (-f $name) { 
     my $dir = $File::Find::dir; 
     my $key = "file". ++$count{ $dir }; 
     $dl{$dir}{$key} = $_; 
     } 
    }; 
    find($path_checker, $root_path); 

    return \%root; 
} 

print encode_json(parse_tree("/tmp")); 
+1

Спасибо! Работает как шарм. Spasibo) – danoaqfd

+1

@danoaqfd вы можете использовать 'print Dumper \% dl, \% count' для проверки внутренней работы. –

+0

Извините за беспокойство снова, но я только что заметил, что он не рекурсивно печатает содержимое каталога, только один уровень и подкаталоги являются подкаталогом ": {}, но у него есть файлы и подкаталоги. – danoaqfd

Смежные вопросы