先日、Twitter眺めてたらそんな感じの処理について見かけたので、楽に実現する方法について考えてみる。

1. tarでディレクトリだけを固める

別々のホスト間で処理する場合、tarでディレクトリだけを固めてしまい、コピー先でそれを展開するという方法が楽そうだ。

cd SourceDir;find ./ -type d -print0 | xargs -0 tar czvf dir.tar.gz --no-recursion # dir.tar.gzにディレクトリだけ固める
cd TargetDir;tar xzvf dir.tar.gz # コピー先にtar.gzを持っていって展開

同一ホストであれば、以下のようにパイプでつなげることでそのまま展開、コピーさせることも可能だ。

cd SourceDir;find ./ -type d -print0 | tar c -O . | tar xvf - -C /TargetDir

同一ホストでなくとも、コピー元から直接ssh接続できる場合は、以下のようにパイプで繋げてやることで直接tarを展開できるので、これを利用するといいだろう。

cd SourceDir;find ./ -type d -print0 | tar c -O . | ssh user@host tar xvf - -C /TargetDir

2. findでの結果をそのまま利用する

findから直接処理する場合、以下のようにコマンドを実行するといいだろう。 パーミッションの取得をするためにprintfオプションが必要になるので、GNU findじゃないと動作しない点に注意が必要。

find ./ -type d -printf "%m %p\n" | xargs -n2 bash -c 'mkdir -p -m $0 /opt/test2/$1'

traと同様、コピー元から直接ssh接続できるようであれば、それで処理することも可能だろう。 一応、リストだけ出力して別のホストに転送してしまえば、それでも処理は可能ではある。