dittoは、アーカイブのファイル名に-を指定すると、標準出力へアーカイブを書き出したり、標準入力からアーカイブを読み込んだりできる。パイプとsshを組み合わせると、一時ファイルを作らずにディレクトリを別のマシンへ転送できる。
参考: 【ditto】コマンドでCPIOアーカイブを作成・展開する
-でアーカイブを標準入出力に流す
ditto -cのアーカイブファイルに-を指定すると、アーカイブを標準出力へ書き出す。ditto -xのアーカイブファイルに-を指定すると、標準入力からアーカイブを読み込んで展開する。
2つをパイプでつなぐと、アーカイブファイルを作らずにディレクトリをコピーできる。
$ ditto -c Scripts - | ditto -x - ./Scripts-copy
$ find Scripts-copy
Scripts-copy
Scripts-copy/run.sh
Scripts-copy/lib
Scripts-copy/lib/util.sh
$ xattr -l Scripts-copy/run.sh
com.apple.provenance:
com.example.note: hello
アーカイブ経由でも、拡張属性などのメタデータは保持される。
-kを付ければzip形式で標準出力へ書き出せる。
$ ditto -c -k --keepParent Scripts - > Scripts.zip
sshで別のMacへ転送する
パイプの間にsshを挟むと、別のMacへディレクトリを転送できる。man dittoで紹介されている例は以下の通り。
$ ditto -c --norsrc Scripts - | ssh rhost ditto -x --norsrc - ./Scripts
ローカルでScriptsディレクトリをCPIOアーカイブにして標準出力へ流し、リモートホストrhost上のditto -xが標準入力から受け取って./Scriptsへ展開する。--norsrcを指定しているため、リソースフォークや拡張属性などのメタデータは転送しない。
メタデータも含めて転送したい場合は、--norsrcを外す。
$ ditto -c Scripts - | ssh rhost ditto -x - ./Scripts
通信量を減らしたい場合は、-zでgzip圧縮する。展開側は圧縮形式を自動で判別するため、-zは不要である。
$ ditto -c -z Scripts - | ssh rhost ditto -x - ./Scripts
メタデータの扱いについては【ditto】拡張属性やACLを保持してコピーする を参照。
Linuxへ転送する
Linuxにはdittoがないが、dittoが作るCPIOアーカイブはLinuxのcpioコマンドで展開できる。--norsrcを指定すると、._で始まるメタデータ用のファイルがアーカイブに含まれない。
$ ditto -c -z --norsrc --keepParent Scripts - | ssh linuxhost 'cd /tmp && gunzip | cpio -id'
Debian bookwormのコンテナで展開した結果は以下の通り。
$ ditto -c -z --norsrc --keepParent Scripts - | docker run --rm -i debian:bookworm-slim sh -c 'apt-get -qq update >/dev/null && apt-get -qq install -y cpio >/dev/null 2>&1; mkdir /out && cd /out && gunzip | cpio -id && find . | sort'
2 blocks
.
./Scripts
./Scripts/lib
./Scripts/lib/util.sh
./Scripts/run.sh
Linuxから受け取る
逆に、Linuxのcpioで作成したアーカイブをditto -xで受け取って展開できる。cpioの-H odcでPOSIX形式を指定しておく。GNU cpioのデフォルト形式のまま送ると、ditto: cpio read error: bad file formatで展開に失敗する。
$ ssh linuxhost 'cd /data && find logs | cpio -o -H odc | gzip' | ditto -x - ./from-linux
$ find from-linux
from-linux
from-linux/logs
from-linux/logs/a.log
