dittoには、APFSのクローンを使ったコピーやファイルシステム圧縮など、コピー方法を細かく制御するオプションがある。ここでは--clone・--hfsCompression・-X・--nocacheと、環境変数DITTO_TEST_OPTIONSをまとめて紹介する。

参考: 【ditto】コマンドでディレクトリをコピーする

--cloneでAPFSのクローンとしてコピーする

--cloneを指定すると、APFSのクローン機能を使ってファイルをコピーする。クローンはコピー元とデータブロックを共有するため、コピーが一瞬で終わり、ディスク容量もほとんど消費しない。

1GBのファイルを含むディレクトリをコピーし、所要時間と空き容量の減少量を比較した結果は以下の通り。

コマンド所要時間空き容量の減少量
ditto src dst0.69秒約1GB
ditto --clone src dst0.01秒ほぼ0
ditto --noclone src dst0.68秒約1GB

macOS 26.6のAPFSで試した結果、オプションなしのdittoはクローンを使わずにデータを複製した。クローンでコピーしたい場合は--cloneを明示する。--nocloneはクローンを使わない指定である。

クローンしたファイルは、どちらかを変更した時点で変更部分だけが別のブロックに書き込まれる。そのため、コピー元とコピー先は独立したファイルとして扱える。

--hfsCompressionでファイルシステム圧縮をかける

--hfsCompressionを指定すると、コピー先のファイルをファイルシステムレベルで圧縮する。圧縮されたファイルは通常のファイルと同じように読み書きでき、ディスク上の使用量だけが小さくなる。

$ seq 1 2000000 > text/nums.txt
$ ditto text t-plain
$ ditto --hfsCompression text t-comp
$ ls -lO t-plain/nums.txt t-comp/nums.txt
-rw-r--r--@ 1 user  wheel  compressed 14888896  9月 27 09:43 t-comp/nums.txt
-rw-r--r--@ 1 user  wheel  -          14888896  9月 27 09:43 t-plain/nums.txt
$ du -k t-plain/nums.txt t-comp/nums.txt
14540	t-plain/nums.txt
3932	t-comp/nums.txt
$ cmp t-plain/nums.txt t-comp/nums.txt && echo same
same

ls -lOでファイルフラグを表示すると、圧縮されたファイルにはcompressedが付く。ファイルサイズは同じだが、duで見たディスク使用量は約4分の1になった。

man dittoでは、--hfsCompressionはシステムファイルのインストールやバックアップ用途向けと説明している。圧縮されたファイルはMac OS X 10.6より前のバージョンでは読めない。

圧縮済みのファイルを展開してコピーする

すでにファイルシステム圧縮されているファイルは、デフォルト(--preserveHFSCompression)では圧縮されたままコピーされる。

$ ditto t-comp t-comp2
$ ls -lO t-comp2/nums.txt
-rw-r--r--@ 1 user  wheel  compressed 14888896  9月 27 09:43 t-comp2/nums.txt

--nopreserveHFSCompressionを指定すると、圧縮を解除してコピーする。

$ ditto --nopreserveHFSCompression t-comp t-comp3
$ ls -lO t-comp3/nums.txt
-rw-r--r--@ 1 user  wheel  - 14888896  9月 27 09:43 t-comp3/nums.txt
$ du -k t-comp3/nums.txt
14540	t-comp3/nums.txt

-Xで別のボリュームに入らない

-Xを指定すると、コピー元のディレクトリ配下に別のボリュームがマウントされていても、そのボリュームの中身はコピーしない。

xsrc/mntにディスクイメージをマウントした状態で比較した結果は以下の通り。

$ hdiutil create -quiet -size 10m -fs APFS -volname dittotest img.dmg
$ hdiutil attach -quiet -nobrowse -mountpoint "$PWD/xsrc/mnt" img.dmg
$ echo remote > xsrc/mnt/remote.txt
$ ditto xsrc x1
$ ditto -X xsrc x2
$ find x1 | sort
x1
x1/local.txt
x1/mnt
x1/mnt/remote.txt
$ find x2 | sort
x2
x2/local.txt
$ hdiutil detach -quiet "$PWD/xsrc/mnt"

-Xを付けると、マウントポイントのmntディレクトリごとコピー対象から外れる。システム全体をバックアップする際に、外付けディスクやネットワークボリュームを巻き込まないようにする用途で使う。

--nocacheでファイルキャッシュを使わない

--nocacheを指定すると、macOSのUnified Buffer Cacheを使わずにファイルを読み書きする。大量のファイルをコピーするときに、コピーしたファイルでキャッシュが埋まり、他のアプリのキャッシュが追い出されるのを避けられる。

man dittoによると、すでにキャッシュに載っているファイルはキャッシュの内容を使う。

DITTO_TEST_OPTIONSで内部の設定を確認する

環境変数DITTO_TEST_OPTIONSに1を設定すると、dittoは実際にはコピーせず、内部のコピー処理に渡す設定の一覧を表示して終了する。オプションの効果を確認したいときに便利である。

$ DITTO_TEST_OPTIONS=1 ditto src dst
src
dst
 copyACLs: true
 copyExtendedAttributes: true
 copyQuarantine: true
 copyResources: true
 crossDevices: true
 persistRestrictedFlags: true
 persistRootlessEAs: true
 preserveHFSPlusCompression: true

ここで紹介したオプションを付けると、対応する設定が変化する。

オプション変化する設定
--clonecloneFiles: trueが追加される
--hfsCompressionuseHFSPlusCompression: trueが追加される
--nopreserveHFSCompressionpreserveHFSPlusCompressionが消える
-XcrossDevices: falseになる
--nocacheuseFilesystemCache: falseが追加される

メタデータ関連のオプションで設定がどう変わるかは【ditto】拡張属性やACLを保持してコピーする を参照。

参考

DITTO Command: Copy directory hierarchies, create and extract archives in macOS