Twitter見てた時、そういう処理の仕方についてわからないというのを見かけたので、一応何かの時のために残しておくことにする。 通常、LinuxやMacに入ってるmvやcpでは、コピー先のディレクトリが無かったら作成するような機能はないので、ひと手間必要になる。
1. findからxargsを使ってコピー、移動させる場合
findからxargsに対象のファイルPATHを渡して、それをcp、mvを使ってコピーや移動をさせる場合。 この場合、コピー時にディレクトリが無いとエラーになってしまうので、一度mkdirで(フォルダがない場合に)生成させる必要がある。 以下、サンプルコード(mvの場合は、cpのとこを書き換え)。
cd /path/from; find ./ -type f ... | xargs -I@ bash -c 'DIR=/path/to/dir;mkdir -p $DIR/$(dirname @);cp @ $DIR/@'
ちゃんとシェルスクリプトとかで書いて対応するなら、forやwhileを使ってやるといいだろう(xargsだと都度プロセス立ち上げるから遅いし)。
find ./ -type f ... | while read -r var;
do
dir=/tmp/test_3;
mkdir -p $dir/$(dirname $var);
cp $var $dir/$var;
done
2. findからrsyncを利用してコピーさせる場合
findの結果に対し、ディレクトリの同期等を行うツールであるrsyncを使って、ディレクトリ構造とセットでコピーすることもできる。 以下、サンプルコード。
rsync -R $(find ./ -type f ...) /path/to/dir
mvと同等の処理(コピー後にオリジナルを削除する)場合は、「--remove-source-files
」オプションを付与する。
rsync --remove-source-files -R $(find ./ -type f ...) /path/to/dir
パイプから渡す場合、コマンド置換してるところをcatにしとけばいいだろう。
3. findからcpの代わりにinstallコマンドを指定する
Makefileなどでよく利用されるinstallコマンドでは、コピー時にPATHがないとディレクトリを自動で作成するオプション(-D)が用意されている。 このため、cpの代わりにxargsから渡してやると、比較的カンタンにディレクトリ構造ごとコピーができる。
find ./ --type ... | xargs -I@ install -D @ /path/to/dir/@
元ファイルの削除をする機能はないので、必要であれば別途findからrmに渡してやるといいだろう。
4. findからtarによるアーカイブ化→展開を利用する場合
tarはディレクトリ構造を保持するので、それを利用する場合。 以下のように、標準入出力でtarのアーカイブ→展開をしてやればいい。
tar cf - $(find ./ -type f -name ...) | tar xf - -C /path/to/dir
こちらも、元ファイルの削除が必要な場合は別途対応が必要。