3

次のようないくつかのパスがあります。

1: /abc/def/some/common/part/xyz/file1.ext
2: /other/path/to/7433/qwe/some/common/part/anotherfile.ext
3: /misc/path/7433/qwe/some/common/part/filexx.ext
4: /2443/totally/different/path/file9988.ext
5: /abc/another/same/path/to/ppp/thisfile.ext
6: /deep1/deep2/another/same/path/to/diffone/filename.ext

共通部分を見つける必要があります-可能なものごとに、たとえば. 可能であれば上記で共通部分を見つけました:

 /some/common/part/ - in the paths 1,2,3
 /another/same/path/to/ - in the 5,6
 /path/to/ - in the 2,5,6
 /path/ - 2,3,4,5,6

等..

これを解決する方法がまったくわかりません-どのアプローチが良いのか

  • 文字列ベース - 文字列の共通部分をいくらか見つけます
  • リストベース - すべてのパスをリストに分割し、共通要素の配列を多少比較します
  • tree-graph - グラフの共通部分をいくらか見つける
  • 他の?

この問題を解決する方法について何らかの指示が得られたら、(おそらく)自分でコーディングできます。そのため、無料のプログラミング サービスは必要ありませんが、開始方法のガイドが必要です。

ここにはすでに私を助けることができるいくつかのCPANモジュールがあると確信していますが、上記の問題に対して30kモジュールのリストから適切な有用なモジュールを見つける方法が本当にわかりません. :(

編集 - 私がこれを必要とするもののために:

約を持っています。10,000 ディレクトリに 200,000 個のファイルがあり、それらの多くは次のように「一緒に属しています」。

/u/some/path/project1/subprojct/file1
/u/backup/of/work/date/project1/subproject/file2
/u/backup_of_backup/of/work/date/project1/subproject/file2
/u/new/addtions/to/projec1/subproject/file3

ファイルは異なる種類 (pdf、画像、ドキュメント、txt など) であり、いくつかは同じです (上記の file2 のように - Digest::MD5 で簡単にフィルタリングできます)。パスの一部 - たとえば、「project1/subproject」など..

別のファイルには同じ MD5 があるため、重複を除外で​​きますが、次のように異なるツリーにあります。

/u/path/some/file
/u/path/lastest_project/menu/file
/u/path/jquery/menu/file
/u/path/example/solution/jquery/menu/file

そのため、ファイルは同じですが (md5 と同じ)、1つのコピーを適切な場所に移動し (他のファイルを削除する必要があります)、「最も使用される」一般的なパスを特定し、タグを収集する必要があります... (古いパス要素はタグ)

背後にあるアイデアは次のとおりです。

  • 同じ md5 ファイルの大部分が共通のパスに保存されている場合 - 1 つのコピーをどこに移動するかを決定できます...

さらに複雑ですが、説明は上記で十分です;)

HDDのエントロピーを下げる必要があるだけです;)

4

2 に答える 2

2

この問題を解決するには、正しいデータ構造が必要です。部分パスをカウントするハッシュはうまく機能します。

use File::Spec;

my %Count_of = ();

while( <DATA> ){
  my @names = File::Spec->splitdir( $_ );

  # remove file
  pop @names;

  # if absolute path, remove empty names at start
  shift @names while length( $names[0] ) == 0;

  # don't count blank lines
  next unless @names;

  # move two cursor thru the names,
  # and count the partial parts
  # created from one to the other
  for my $i ( 0 .. $#names ){
    for my $j ( $i .. $#names ){
      my $partial_path = File::Spec->catdir( @names[ $i .. $j ] );
      $Count_of{ $partial_path } ++;
    }
  }
}

# now display the results
for my $path ( sort { $Count_of{$b} <=> $Count_of{$a} || $a cmp $b } keys %Count_of ){

  # skip if singleton.
  next if $Count_of{ $path } <= 1;

  printf "%3d : %s\n", $Count_of{ $path }, $path;
}


__DATA__
/abc/def/some/common/part/xyz/file1.ext
/other/path/to/7433/qwe/some/common/part/anotherfile.ext
/misc/path/7433/qwe/some/common/part/filexx.ext
/2443/totally/different/path/file9988.ext
/abc/another/same/path/to/ppp/thisfile.ext
/deep1/deep2/another/same/path/to/diffone/filename.ext
于 2013-06-30T14:26:42.063 に答える