試した環境
- WSL バージョン: 1.2.5.0
- Ubuntu 20.04.5 LTS (GNU/Linux 5.15.90.1-microsoft-standard-WSL2 x86_64)
- GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
- cp (GNU coreutils) 8.30
本題
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