ファイル内容へのハードリンクとディレクトリ構造へのシンボリックリンクを使用してディレクトリツリーをミラーリングします。

ファイル内容へのハードリンクとディレクトリ構造へのシンボリックリンクを使用してディレクトリツリーをミラーリングします。

たとえば、ディレクトリ全体を次の構造を持つ新しいディレクトリ(たとえば)にミラーリングする最良の方法original/は何ですか?mirror/mirror/data/mirror/tree/

  • ディレクトリまたはサブディレクトリoriginal/内のすべてのファイルはハードリンクされています。文書存在するmirror/data
    • ファイル名は、コンテンツのハッシュなどのコンテンツの一意の識別子です。
    • mirror/treeで、ソースファイルの相対パスと相対パスが一致する点から始まり、シンボリックリンクされますoriginal

簡単に復元できるように?

この機能を既存のツールとして実装できますか? - ファイルの内容に基づいて一意の識別子を生成するために柔軟にコマンドを選択できるコマンド。


たとえば、ファイルが1つだけで、original/something「data」という単語を含むテキストファイルであるとします。その後、スクリプトまたはコマンドを実行し、original結果は次のようになります。

$  tree original mirror
original
└── something
mirror
├── data
│   └── 6667b2d1aab6a00caa5aee5af8…
└── tree
    └── original
        └── something -> ../../data/6667b2d1aab6a00caa5aee5af8…

5 directories, 3 files

ここで、ファイル667b…はハードリンクoriginal/somethingであり、そのファイル名はファイルのsha256sumハッシュです。読みやすくするためにファイル名を短くしましたので、参考にしてください。

鏡を通して元の姿を完璧に再現したかったです。

これを行うためにスクリプトを書くことができることを知っていますが、そうする前に間違いを犯していくつかのデータが失われる可能性があり、すでにこれを安全に実行するツールがあるかどうかを知りたいです。 )遠く)または落とし穴がある場合。

背景: 名前が変更されたディレクトリを追跡するアーカイブを保持したいのですが、バージョン管理は不要です。git-annexGitリポジトリの使用には多くのオーバーヘッドがあることがわかっていますが、ディレクトリの内容をファイル名がその内容のハッシュファイルにミラーリングするには、ディレクトリ構造へのシンボリックリンクを使用する必要があります。その後、git-diffを使用して名前の変更を追跡できます。私はgit-annexが何をしているのか完全に理解していないので、私のデータを保持することを信頼したくありません。だから私はより軽くて邪魔にならない選択肢を探しています。

答え1

実装することはそれほど難しくありません。 GNUシステム(ln -rおよびsha1sum -z)と次のようにzsh

mkdir -p mirror/{data,tree} &&
  find original -type f -exec sha1sum -z {} + |
    while IFS= read -rd '' rec; do
      sum=$rec[1,40] file=$rec[43,-1]
      ln -f -- $file mirror/data/$sum &&
        mkdir -p -- mirror/tree/${${file#*/}:h} &&
        ln -rs mirror/data/$sum mirror/tree/${file#*/}
    done

ディレクトリのメタデータ(所有権、権限、mtime / atime、ACL、拡張属性)を保存しようとしません。複数のファイルの内容が同じ場合、リンクされるファイルは報告される順序(定義されていない)mirror/dataによって異なります。find

また、空のディレクトリやディレクトリや通常のファイル以外のファイル(シンボリックリンク、fifos、デバイスなど)はコピーされません。

GNUを使用して、特殊ファイルとできるだけ多くのメタデータを含むディレクトリ構造をコピーできますtar

set -o pipefail
mkdir -p mirror/{data,tree} &&
  (
    cd original && find . ! -type f -print0 |
      tar -cf - --xattrs --null --verbatim-files-from --no-recursion -T -
  ) | (
    cd mirror/tree && tar -xpf - --xattrs
  ) &&
  find original -type f -exec sha1sum -z {} + |
    while IFS= read -rd '' rec; do
      sum=$rec[1,40] file=$rec[43,-1]
      ln -f -- $file mirror/data/$sum &&
        ln -rs mirror/data/$sum mirror/tree/${file#*/}
    done

ただし、これらのディレクトリにこれらのシンボリックリンクを作成すると、最後の変更時刻が更新されます。

関連情報