LoginSignup
16
9

More than 5 years have passed since last update.

cp -r はコピー先ディレクトリが存在するかで動作が異なる

Posted at

すごく基本的なことだと思うのですが
自分は知らなかった cp -r の動作についてです。

基本中の基本のディレクトリの再帰的コピー

あるディレクトリとその中にファイルを入れたとします:

mkdir /tmp/dir1 && touch /tmp/dir1/some.txt

ここでディレクトリ dir1 内には some.txt が生成されました。

次に、この dir1dir2 としていつものようにコピーします:

cp -r /tmp/dir1 /tmp/dir2 && ls -la /tmp/dir*

結果は予想通り、同じ構造をもったディレクトリ dir1, dir2 ができました:

1回目
/tmp/dir1:
total 0
drwxr-xr-x   3 user  wheel   96 Feb 15 11:58 .
drwxrwxrwt  19 root  wheel  608 Feb 15 11:58 ..
-rw-r--r--   1 user  wheel    0 Feb 15 11:58 some.txt

/tmp/dir2:
total 0
drwxr-xr-x   3 user  wheel   96 Feb 15 11:58 .
drwxrwxrwt  19 root  wheel  608 Feb 15 11:58 ..
-rw-r--r--   1 user  wheel    0 Feb 15 11:58 some.txt

2 回目のコピー

ここで、更に先ほどのコピーのコマンドを実行します:

cp -r /tmp/dir1 /tmp/dir2 && ls -la /tmp/dir*

この結果は先程の結果とは異なり、
dir2 内に dir1 が子としてコピーされています:

2回目
/tmp/dir1:
total 0
drwxr-xr-x   3 user  wheel   96 Feb 15 11:58 .
drwxrwxrwt  19 root  wheel  608 Feb 15 11:58 ..
-rw-r--r--   1 user  wheel    0 Feb 15 11:58 some.txt

/tmp/dir2:
total 0
drwxr-xr-x   4 user  wheel  128 Feb 15 11:58 .
drwxrwxrwt  19 root  wheel  608 Feb 15 11:58 ..
drwxr-xr-x   3 user  wheel   96 Feb 15 11:58 dir1
-rw-r--r--   1 user  wheel    0 Feb 15 11:58 some.txt

この動作の違いは
cp -r では最後に指定されたコピー先がディレクトリの場合、
指定したファイルをディレクトリ内に作成するようになっているためです。

そのため、コピー先が存在する場合は cp -r の動作は
コピー先が存在しない初回とは違う結果になるというわけです。

よくあるバッチをさっくり書いて定常的に動かしていると
いつのまにか意図しない結果になっているしれないので注意が必要ですね。

私は恥ずかしながらこの動作を知らず
冪等性のある操作だと思っていました……。
ずっと使ってきたのに。

いつも同じ動作にしたいときは?

-T (--no-target-directory) オプションを追加します。

このオプションを追加すると、
先程のようにコピー先のディレクトリが存在する場合でも
そのままディレクトリごとコピーされます:

cp -rT /tmp/dir1 /tmp/dir2 && ls -la /tmp/dir*


ただし、このオプションは GNU 版の cp にしかないと思われて、
Mac や BSD の子孫の cp ではディレクトリを移動して差し替えか、
単に削除しておくということが必要そうです。
(実はいいやりかたがあれば教えてください)

以上、無知の知でした。

16
9
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
9