dittoの--bomオプションを使うと、BOM(Bill of Materials)ファイルに記載されたファイルやディレクトリだけを選んでコピーできる。BOMファイルはmkbomで作成し、lsbomで中身を確認する。
BOMファイルとは
BOMファイルは、ファイルやディレクトリのパス・パーミッション・所有者・サイズ・チェックサムなどを記録したmacOS独自の形式のファイルである。macOSのインストーラーパッケージ(.pkg)は、インストールするファイルの一覧をBOMファイルとして持っている。インストール済みパッケージのBOMファイルは/var/db/receipts/に保存される。
mkbomでBOMファイルを作成する
mkbom <ディレクトリ> <BOMファイル>で、ディレクトリ配下の全ファイルを記録したBOMファイルを作成する。
$ find src -type f | sort
src/bin/tool
src/docs/a.md
src/docs/b.md
src/tmp/cache.log
$ mkbom src full.bom
lsbomでBOMファイルの中身を確認する。
$ lsbom full.bom
. 40755 501/0
./bin 40755 501/0
./bin/tool 100644 501/0 2 2192966820
./docs 40755 501/0
./docs/a.md 100644 501/0 2 2418082923
./docs/b.md 100644 501/0 2 2454254050
./tmp 40755 501/0
./tmp/cache.log 100644 501/0 2 2333201024
-sを付けるとパスだけを表示する。
$ lsbom -s full.bom
.
./bin
./bin/tool
./docs
./docs/a.md
./docs/b.md
./tmp
./tmp/cache.log
一部のファイルだけを記録したBOMファイルを作る
mkbom -iを使うと、lsbomの出力形式のテキストファイルからBOMファイルを作成できる。lsbomの出力から不要な行を取り除けば、特定のファイルを除外したBOMファイルになる。
tmpディレクトリを除外したBOMファイルを作る例は以下の通り。
$ lsbom full.bom | grep -v '^\./tmp' > list.txt
$ mkbom -i list.txt part.bom
$ lsbom -s part.bom
.
./bin
./bin/tool
./docs
./docs/a.md
./docs/b.md
mkbom -iに渡すテキストには、パスだけでなくパーミッションや所有者の列も必要である。lsbom -sの出力をそのまま渡すとmkbom: Not enough fieldsのエラーになる。
また、ファイルの親ディレクトリの行も必要である。親ディレクトリの行を含めずにファイルの行だけを渡すと、BOMファイルに登録されない。
$ lsbom full.bom | grep '^\./docs/a.md' > list3.txt
$ mkbom -i list3.txt p3.bom
parent directory ./docs does not exist
mkbom: Can't insert ./docs/a.md
--bomでBOMファイルに載っているファイルだけをコピーする
ditto --bom <BOMファイル> <コピー元> <コピー先>の形式で実行すると、BOMファイルに記載されたファイルとディレクトリだけをコピーする。
$ ditto --bom part.bom src dst
$ find dst | sort
dst
dst/bin
dst/bin/tool
dst/docs
dst/docs/a.md
dst/docs/b.md
tmpディレクトリはBOMファイルに含まれていないため、コピーされない。
BOMファイルはコピー対象のパスを選ぶためだけに使われる。BOMファイル作成後にファイルの内容が変わっていても、コピー元の現在の内容がそのままコピーされる。BOMファイルに記載されていてもコピー元に存在しないファイルは、エラーを出さずに飛ばされる。
BOMファイルに1つもファイルが含まれていない場合は、警告が表示されて何もコピーされない。
$ ditto --bom p3.bom src dst3
ditto: WARNING: bom p3.bom contains no files, nothing copied
インストール済みパッケージのファイルだけをコピーする
/var/db/receipts/にあるBOMファイルを使うと、特定のパッケージでインストールされたファイルだけを取り出せる。
python.orgのインストーラーで入れたPython 3.11のパッケージのうち、/usr/local/binへコマンドを配置するorg.python.Python.PythonUnixTools-3.11を例にする。BOMファイル内のパスは、パッケージのインストール先(location)からの相対パスになっている。
$ pkgutil --pkg-info org.python.Python.PythonUnixTools-3.11
package-id: org.python.Python.PythonUnixTools-3.11
version: 0
volume: /
location: usr/local/bin
install-time: 1734194695
$ lsbom -s /var/db/receipts/org.python.Python.PythonUnixTools-3.11.bom
.
./2to3
./2to3-3.11
./idle3
./idle3.11
./pydoc3
./pydoc3.11
./python3
./python3-config
./python3-intel64
./python3.11
./python3.11-config
./python3.11-intel64
コピー元にインストール先の/usr/local/binを指定する。
$ ditto --bom /var/db/receipts/org.python.Python.PythonUnixTools-3.11.bom /usr/local/bin pytools
$ ls -1 pytools
2to3
2to3-3.11
idle3
idle3.11
pydoc3
pydoc3.11
python3
python3-config
python3-intel64
python3.11
python3.11-config
python3.11-intel64
/usr/local/binには他のツールのファイルも混在しているが、BOMファイルに記載されたPython関連のファイルだけがコピーされる。
