あなたの「必」の書き順を教えてください

任意のディレクトリ構造を分析してその構造(ファイル名を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'
                   }
    };

A 回答 (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;
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/05/30 11:24

再帰的に追加するロジックでそれっぽく作ってみました。




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 にファイル構造が入ってます。
ただし、私の独自の構造でいれていますのでご了承ください。
    • good
    • 0

規則がまるでわかりません。


たとえば
      'test2' => {
           'data1' => 
                        {
                      'path' => 'test1/data.txt',
                      'parent_dir' => 'test2'


んなんで path => 'test1/data.txt'になるのでしょうか?
test2の下にいて、ファイル名はdata1.txtなのに。

いずれにしろほとんど組んでくださいとしか読めない質問なので
答えようがないです。
    • good
    • 0
この回答へのお礼

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

→規則がまるでわかりません。
申し訳ない。

お礼日時:2008/05/30 11:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報