dittoはmacOS標準搭載のコピーコマンド。ディレクトリ階層のコピーに加えて、zipやCPIO形式のアーカイブの作成・展開もできる。ここではディレクトリとファイルをコピーする基本的な使い方をまとめる。

ディレクトリをコピーする

ditto <コピー元> <コピー先>の形式で実行する。

$ ditto src dst
$ find dst
dst
dst/a.txt
dst/sub
dst/sub/b.txt

コピー先のディレクトリが存在しない場合は自動で作成される。途中のディレクトリも含めて作成されるため、mkdir -pは不要である。

$ ditto src x/y/z
$ find x
x
x/y
x/y/z
x/y/z/a.txt
x/y/z/sub
x/y/z/sub/b.txt

cp -rとの違い

dittoは、コピー先のディレクトリが存在するかどうかに関わらず、常にコピー元ディレクトリの中身をコピー先へコピーする。

cp -rはコピー先がすでに存在する場合、コピー元ディレクトリそのものをコピー先の中に作る。

$ mkdir dst3 dst4
$ cp -r src dst3
$ ditto src dst4
$ find dst3 dst4
dst3
dst3/src
dst3/src/a.txt
dst3/src/sub
dst3/src/sub/b.txt
dst4
dst4/a.txt
dst4/sub
dst4/sub/b.txt

cp -rではdst3/src/ができるが、dittoではdst4/直下に中身が展開される。man dittoのBUGSセクションでも、この挙動の違いに触れている。

また、dittoはファイルの更新日時・パーミッション・所有者・グループをコピー元に合わせる。cpをオプションなしで実行した場合、更新日時を保持しない。

$ ditto src/a.txt t1.txt
$ cp src/a.txt t2.txt
$ ls -l src/a.txt t1.txt t2.txt
-rw-r--r-- 1 user 6  1月  1  2020 src/a.txt
-rw-r--r-- 1 user 6  1月  1  2020 t1.txt
-rw-r--r-- 1 user 6  9月 27 09:20 t2.txt

加えて、dittoは拡張属性やACLなどのmacOS固有のメタデータもデフォルトで保持する。メタデータの扱いについては【ditto】拡張属性やACLを保持してコピーする を参照。

既存のディレクトリにマージする

コピー先のディレクトリがすでに存在する場合、コピー元の内容が既存の内容にマージされる。同名のファイルは上書きされ、コピー元に存在しないファイルはそのまま残る。

$ find other
other
other/a.txt
other/c.txt
$ ditto other dst
$ find dst
dst
dst/a.txt
dst/c.txt
dst/sub
dst/sub/b.txt

dst/sub/b.txtはそのまま残り、other/c.txtが追加され、dst/a.txtはother/a.txtの内容で上書きされる。rsync --deleteのように、コピー元に存在しないファイルを削除する機能はない。

複数のディレクトリをまとめてコピーする

コピー元を複数指定すると、それぞれの中身を1つのコピー先ディレクトリにまとめてコピーする。

$ ditto src other multi
$ find multi
multi
multi/a.txt
multi/c.txt
multi/sub
multi/sub/b.txt

ファイルをコピーする

ファイル単体をコピーする場合は、ditto <コピー元ファイル> <コピー先ファイル>の形式で実行する。コピー先の途中のディレクトリは自動で作成される。

$ ditto src/a.txt f/g/copy.txt
$ find f
f
f/g
f/g/copy.txt

コピー先に既存のディレクトリを指定すると、ディレクトリの中に同名のファイルとしてコピーされる。

$ mkdir d1
$ ditto src/a.txt d1
$ find d1
d1
d1/a.txt

-v・-Vでコピーの経過を表示する

dittoはデフォルトでは何も出力しない。-vを指定すると、コピー元のディレクトリごとに1行出力する。

$ ditto -v src v1
Copying src

-Vを指定すると、ファイルごとにコピーしたバイト数まで出力する。

$ ditto -V src v2
>>> Copying src
copying file ./sub/b.txt ...
6 bytes for ./sub/b.txt
copying file ./a.txt ...
6 bytes for ./a.txt

どちらも出力先は標準エラー出力である。

参考

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