dittoは、ファイルの拡張属性・ACL・リソースフォーク・quarantine(検疫)情報といったmacOS固有のメタデータをデフォルトで保持してコピーする。オプションを指定すると、メタデータの種類ごとに保持するかどうかを切り替えられる。

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

デフォルトでメタデータを保持する

検証用に、拡張属性とquarantine情報を付けたファイルを用意する。

$ mkdir src
$ echo hi > src/a.txt
$ xattr -w com.example.note "hello" src/a.txt
$ xattr -w com.apple.quarantine "0081;66f5a000;Safari;" src/a.txt
$ xattr -l src/a.txt
com.apple.provenance:
com.apple.quarantine: 0081;66f5a000;Safari;
com.example.note: hello

com.apple.provenanceは、xattr -wで付けた属性とは別に、macOSがファイルへ付与する属性である。以降の結果でもdittoのオプションに関係なく表示される。

オプションなしでdittoを実行すると、拡張属性とquarantine情報がコピー先にも付く。

$ ditto src dst
$ xattr -l dst/a.txt
com.apple.provenance:
com.apple.quarantine: 0281;6ab861d3;;
com.example.note: hello

com.apple.quarantineの値はコピー元と異なる。dittoはquarantine情報を拡張属性としてそのまま複製するのではなく、quarantine情報として付け直す。macOS 26.6の環境で試した結果では、フラグと時刻が書き換わり、ダウンロード元アプリ名(Safari)は空になった。

ACLも同様に保持される。

$ chmod +a "everyone allow read" src/a.txt
$ ls -le src/a.txt
-rw-r--r--@ 1 user  wheel  3  9月 27 09:22 src/a.txt
 0: group:everyone allow read
$ ditto src dst
$ ls -le dst/a.txt
-rw-r--r--@ 1 user  wheel  3  9月 27 09:22 dst/a.txt
 0: group:everyone allow read

cp -RはACLを保持しない。

$ cp -R src dst2
$ ls -le dst2/a.txt
-rw-r--r--@ 1 user  wheel  3  9月 27 09:23 dst2/a.txt

保持するメタデータを切り替えるオプション

メタデータの種類ごとに、保持する・しないを指定するオプションがある。

保持する(デフォルト)保持しない対象
--rsrc--norsrcリソースフォークとHFSメタデータ
--extattr--noextattr拡張属性
--acl--noaclACL
--qtn--noqtnquarantine情報

同じ種類の保持する・しないオプションを両方指定した場合は、後に指定したほうが優先される。

--norsrcでメタデータをまとめて除外する

--norsrcを指定すると、リソースフォークに加えて、拡張属性・ACL・quarantine情報もまとめて除外する。

$ ditto --norsrc src dst
$ xattr -l dst/a.txt
com.apple.provenance:
$ ls -le dst/a.txt
-rw-r--r--@ 1 user  wheel  3  9月 27 09:22 dst/a.txt

リソースフォークは、拡張属性com.apple.ResourceForkとして確認できる。--norsrcを指定すると、ファイル本体だけがコピーされる。

$ xattr -w com.apple.ResourceFork "resourcedata" src/r.txt
$ ditto src dst1
$ ls -l@ dst1/r.txt
-rw-r--r--@ 1 user  wheel  4  9月 27 09:23 dst1/r.txt
	com.apple.ResourceFork	12
	com.apple.provenance	11
$ ditto --norsrc src dst2
$ ls -l@ dst2/r.txt
-rw-r--r--@ 1 user  wheel  4  9月 27 09:23 dst2/r.txt
	com.apple.provenance	11

--norsrcと保持する側のオプションを組み合わせると、特定のメタデータだけ残せる。たとえば--norsrc --extattrでは拡張属性だけを残す。

$ ditto --norsrc --extattr src dst
$ xattr -l dst/a.txt
com.apple.provenance:
com.apple.quarantine: 0081;66f5a000;Safari;
com.example.note: hello

個別のメタデータを除外する

--noextattrは拡張属性を除外する。ただしquarantine情報は--noextattrの対象外であり、コピー先に付く。

$ ditto --noextattr src dst
$ xattr -l dst/a.txt
com.apple.provenance:
com.apple.quarantine: 0281;6ab861fe;;

--noaclはACLだけを除外する。

$ ditto --noacl src dst
$ ls -le dst/a.txt
-rw-r--r--@ 1 user  wheel  3  9月 27 09:22 dst/a.txt

--noqtnだけではquarantine情報が残る

--noqtnは「quarantine情報を保持しない」オプションである。しかし--noqtnだけを指定しても、コピー先にはcom.apple.quarantineが残る。

$ ditto --noqtn src dst
$ xattr -l dst/a.txt
com.apple.provenance:
com.apple.quarantine: 0081;66f5a000;Safari;
com.example.note: hello

--noqtnで止まるのは、dittoによるquarantine情報の付け直しだけである。拡張属性のコピーは有効なままなので、com.apple.quarantineは通常の拡張属性として元の値のまま複製される。

DITTO_TEST_OPTIONS=1を付けて実行すると、実際にはコピーせずにditto内部のコピー設定を表示する。--noqtnを付けるとcopyQuarantineだけが消え、copyExtendedAttributesは残る。

$ 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
$ DITTO_TEST_OPTIONS=1 ditto --noqtn src dst
src
dst
 copyACLs: true
 copyExtendedAttributes: true
 copyResources: true
 crossDevices: true
 persistRestrictedFlags: true
 persistRootlessEAs: true
 preserveHFSPlusCompression: true

quarantine情報を確実に外すには、--noqtnと--noextattrを組み合わせる。

$ ditto --noqtn --noextattr src dst
$ xattr -l dst/a.txt
com.apple.provenance:

他の拡張属性を残したい場合は、コピー後にxattr -d com.apple.quarantineで削除する。

環境変数DITTONORSRCで一括指定する

環境変数DITTONORSRCを設定すると、--norsrc --noextattr --noacl --noqtnを指定した場合と同じ動作になる。

$ DITTONORSRC=1 ditto src dst
$ xattr -l dst/a.txt
com.apple.provenance:

DITTONORSRCを設定した状態で特定のメタデータだけ残したい場合は、--rsrcと組み合わせて指定する。--extattrや--aclは--rsrcを前提とするオプションである。単独で指定してもDITTONORSRCの設定が優先された。

$ DITTONORSRC=1 ditto --rsrc --extattr src dst
$ xattr -l dst/a.txt
com.apple.provenance:
com.apple.quarantine: 0081;66f5a000;Safari;
com.example.note: hello

参考

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