linux

Linux cp parentsオプション 特定ファイル・ディレクトリパスをそのまま維持して再帰的にコピーする

以下のような構成で dir_1 を起点としてファイル・ディレクトリパスはそのままに dir_3 配下のみ再帰的にコピーしたり、dir_2/hoge.txtのみコピーしたいときが稀にあります。

$ tree .
.
├── dir_1
│   └── dir_2
│       ├── dir_3             ・・・・・・ 例2: dir_1起点でこのディレクトリ配下をコピーしたい
│       │   └── dir_4
│       │       └── eg_2.txt
│       └── eg_1.txt          ・・・・・・ 例1: dir_1起点でこのファイルをコピーしたい
└── dir_a
    └── dir_b

6 directories, 2 files
$ 


その場合は、parentsオプションを使用します。上記例1であれば以下のように実行します。

$ man cp 
.....
       --parents
              use full source file name under DIRECTORY
.....
$ 
$ cp --parents dir_1/dir_2/eg_1.txt  dir_a/dir_b/
$
$ tree .
.
├── dir_1
│   └── dir_2
│       ├── dir_3
│       │   └── dir_4
│       │       └── eg_2.txt
│       └── eg_1.txt
└── dir_a
    └── dir_b
        └── dir_1     ・・・・・・ dir1 のパスから再帰的にコピーされた
            └── dir_2
                └── eg_1.txt

8 directories, 3 files
$ 


上記例2のディレクトリであれば-r オプションを併用します。

$ cp -r --parents dir_1/dir_2/dir_3 dir_a/dir_b/
$
$ tree .
.
├── dir_1
│   └── dir_2
│       ├── dir_3
│       │   └── dir_4
│       │       └── eg_2.txt
│       └── eg_1.txt
└── dir_a
    └── dir_b
        └── dir_1      ・・・・・・ dir1 のパスから再帰的にコピーされた
            └── dir_2
                └── dir_3
                    └── dir_4
                        └── eg_2.txt

10 directories, 3 files
$ 


実用例としては、

  • ログをそのままのパスでバックアップする。(rsyncの場合は-R)
  • 複数のサーバ(やユーザー)で同じリソースを保存する際、名前が重複しないようにそれぞれ保存する

など挙げられます。

以下は各ユーザーのssh鍵をかき集める例です。

$ sudo sh -c 'for i in `ls -1 /home/`;do  cp --parents /home/$i/.ssh/id_rsa .  ; done' 
$
$ sudo find home/ -type f 
home/ec2-user/.ssh/id_rsa
home/ec2-user-2/.ssh/id_rsa
home/ec2-user-3/.ssh/id_rsa
$ 


NG例というか当然というか補足ですが、-r オプションのみであると対象が、コピー先直下にコピーされたり

$ cp -r dir_1/dir_2/eg_1.txt  dir_a/dir_b/
$ 
$ tree .
.
├── dir_1
│   └── dir_2
│       ├── dir_3
│       │   └── dir_4
│       │       └── eg_2.txt
│       └── eg_1.txt
└── dir_a
    └── dir_b
        └── eg_1.txt   ・・・・・・ ファイルのみコピーされる

6 directories, 3 files
$  


コピー対象外としたいものまでコピーされます。

$ cp -r dir_1/  dir_a/dir_b/
$ 
$ tree .
.
├── dir_1
│   └── dir_2
│       ├── dir_3
│       │   └── dir_4
│       │       └── eg_2.txt
│       └── eg_1.txt
└── dir_a
    └── dir_b
        └── dir_1       ・・・・・・ dir_1 配下がすべてコピーされる
            └── dir_2
                ├── dir_3
                │   └── dir_4
                │       └── eg_2.txt
                └── eg_1.txt

10 directories, 4 files
$ 


以上です。(´・ω・`)ノシ