• ベストアンサー

ディレクトリ構造の表示

任意のディレクトリ構造を分析してその構造(ファイル名をkey)をXMLなりハッシュに吐き出すことができるモジュールなり方法を模索しています。 XMLでいうXML::Simpleみたいなものです。 参考------------------------------------------------------ 【XML分析:XML::Simple】→【ハッシュ:Data::Dumper】 【XML分析:XML::Simple】→【XMLファイル:XML::Simple】 ---------------------------------------------------------- グーグルなどで検索してみた限りでは、任意のディレクトリ内分析をしてくれてXMLなりハッシュに吐き出してくれるモジュールはなさそう。 そこでFile::Pathを使ってディレクトリ内を洗ってその構造を動的にハッシュにしたいと考えいます。しかし残念なことに予め構造がわかっている規則的なデータを動的にハッシュにすることはできるのですが、実際に分析するまでその階層すらわからない不規則なツリー状のデータ構造を動的にハッシュ化するプログラミング能力を持ち合わせていません。 そこで質問しかないということになりました。ぜひお知恵をお借りしたいと思っています。よろしくお願いいたします。 本当に簡単ですがこのような不規則なディレクトリ構造を動的にハッシュにしたいと思っています。この例ではディレクトリ構造がわかってますが、分析するまでわからないものとしてみて頂ければと思います。 test1(dir)―――――test2(dir)――――――――data1.txt(file)            |           |            ―data1.txt(file)   ―data2.txt(file)            |            ―data2.txt(file) $test1 = {       'test2' => {            'data1' =>                          {                       'path' => 'test1/data.txt',                       'parent_dir' => 'test2'                         },            'data2' =>                          {                       'path' => 'test2/data.txt',                       'parent_dir' => 'test2'                         },                 },       'data1' =>                     {                  'path' => 'test1/data.txt',                  'parent_dir' => 'test1'                    },       'data2' =>                     {                  'path' => 'test2/data.txt',                  'parent_dir' => 'test1'                    }     };

質問者が選んだベストアンサー

  • ベストアンサー
  • atom_seed
  • ベストアンサー率48% (25/52)
回答No.3

仕上がりの構造を分かりやすくしてみました。 my $dom = { '/path' => '.' }; my @dir = ($dom); while ( my $dir = shift @dir ) {   opendir( DIR, $dir->{'/path'} );   my @path    = split( '/', $dir->{'/path'} );   my $current_dir = pop @path;   my $parent_dir = pop @path;   while ( my $path = readdir(DIR) ) {     next if ( $path =~ /^\.\.?$/ );     my $full_path = "$dir->{'/path'}/$path";     $dir->{$current_dir} ||= [];     if ( -d $full_path ) {       push( @dir, { '/path' => $full_path } );       push( @{ $dir->{$current_dir} }, $dir[-1] );     }     else {       push(         @{ $dir->{$current_dir} },         {  'file_name'  => $path,           'full_path'  => $full_path,           'current_dir' => $current_dir,           'parent_dir' => $parent_dir,         }       );     }   }   delete $dir->{'/path'};   closedir DIR; } # 動作確認(モジュールがないときはインストールしてください) use Data::Dumper; print Data::Dumper->new( [$dom] )->Indent(1)->Sortkeys(1)->Dump; exit;

takahathi
質問者

お礼

返信ありがとうございました。 動作確認いたしたました。私より数段上の実力の方とお見受けいたしました。ありがとうございます。 初見の書き方もあって正直わからない部分もありますが、この質問をするまでかなり検索で調べたのですが、なかなか糸口がみつからず・・・あきらめかけていました。 書き方の取っ掛かりが見つかりました。これから一個ずつ動作チェックしながら勉強します。ありがとうございました。

その他の回答 (2)

  • atom_seed
  • ベストアンサー率48% (25/52)
回答No.2

再帰的に追加するロジックでそれっぽく作ってみました。 my $dom = { 'path' => '.', 'list' => [] }; my @dir = ($dom); while ( my $dir = shift @dir ) {   opendir( DIR, $dir->{'path'} );   while ( my $path = readdir(DIR) ) {     next if ( $path =~ /^\.\.?$/ );     my $long_path = "$dir->{'path'}/$path";     if ( -d $long_path ) {       push( @dir, { 'path' => $long_path, 'list' => [] } );       push( @{ $dir->{'list'} }, $dir[-1] );     }     else {       push( @{ $dir->{'list'} }, $path );     }   }   closedir DIR; } $dom にファイル構造が入ってます。 ただし、私の独自の構造でいれていますのでご了承ください。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

規則がまるでわかりません。 たとえば       'test2' => {            'data1' =>                          {                       'path' => 'test1/data.txt',                       'parent_dir' => 'test2' は んなんで path => 'test1/data.txt'になるのでしょうか? test2の下にいて、ファイル名はdata1.txtなのに。 いずれにしろほとんど組んでくださいとしか読めない質問なので 答えようがないです。

takahathi
質問者

お礼

→'path' => 'test1/data.txt', の部分は申し訳ないです。見落としました。空白を入れて整形しているときに誤ってペーストしてしまいました。 この掲示板では修正ができないので・・・。 →規則がまるでわかりません。 申し訳ない。

関連するQ&A