cp コマンドの --parents オプションでディレクトリ構成を保持したまま特定のファイルだけコピーする。

試した環境

本題

cp コマンドで --parents オプションを指定することでディレクトリ構成を保持したままコピーできます。 つまりは以下のようにコピーできます。

$ mkdir -p source/subdir destination
$ touch source/subdir/example.txt  source/subdir/example2.txt
$ cd source
$ cp --parents subdir/example.txt ../destination/
$ cd ..
$ $ tree
.
├── destination
│   └── subdir
│       └── example.txt
└── source
    └── subdir
        ├── example.txt
        └── example2.txt

この --parents オプションは複数のディレクトリに対して特定のファイルをコピーしたいときに役立つと思います。 例えば、以下のようなディレクトリ構成を考えます。

$ tree
.
└── results
    ├── condition00
    │   ├── output.heavy
    │   ├── stderr.log
    │   └── stdout.log
    ├── condition01
    │   ├── output.heavy
    │   ├── stderr.log
    │   └── stdout.log
#   ...省略
    └── condition99
        ├── output.heavy
        ├── stderr.log
        └── stdout.log

output.heavy はサイズがとても大きいファイルだとします。 このとき全ての condition?? ディレクトリ下のlogファイルだけをコピーしたい場合、以下の通り実行します。

mkdir -p /path/to/destination/
cd results
find . -type f -name "*.log" -print0 | xargs -0 -I{} cp -a --parents {} /path/to/destination/
$ tree  /path/to/destination/
/path/to/destination/
├── condition00
│   ├── stderr.log
│   └── stdout.log
├── condition01
│   ├── stderr.log
│   └── stdout.log
#   ...省略
└── condition99
    ├── stderr.log
    └── stdout.log

もし output.heavy がコピーの負担が小さいファイルのならば、ディレクトリ全体をコピーしてから不要なファイルを削除する方法をとるかもしれません。

cp -a results/* /path/to/destination/
find /path/to/destination/ -type f -name "output.heavy" -delete

logファイル以外のファイルサイズが大きかったり、logファイル以外のファイル数が多い場合は、 --parents オプションを使った cp が有効なのではないかと思います。

参考

man cp