BSDのcpコマンドでディレクトリごと同じ名前で再帰的にコピーしたい
- 環境 : macOS Mojave バージョン10.14.2
例えばこんなディレクトリ構成
$ find .
.
./chovin
./pon
./pon/su
./pon/su/ke
./pon/su/ke/tarou.txt
./pon/su/symbolicklink
# シンボリックリンクも入っています
$ ls -lR
total 0
drwxr-xr-x 2 mana staff 64 12 27 16:06 chovin
drwxr-xr-x 4 mana staff 128 12 27 16:19 pon
./chovin:
./pon:
total 0
drwxr-xr-x 4 mana staff 128 12 27 16:20 su
./pon/su:
total 0
drwxr-xr-x 3 mana staff 96 12 27 14:47 ke
lrwxr-xr-x 1 mana staff 32 12 27 16:20 symbolicklink -> /Users/mana/Downloads/pon/su/ke/
./pon/su/ke:
total 0
-rw-r--r-- 1 mana staff 0 12 27 14:47 tarou.txt
正解
$ cp -R pon chovin
$ find .
.
./chovin
./chovin/pon
./chovin/pon/su
./chovin/pon/su/ke
./chovin/pon/su/ke/tarou.txt
./chovin/pon/su/symbolicklink
./pon
./pon/su
./pon/su/ke
./pon/su/ke/tarou.txt
./pon/su/symbolicklink
cp: pon is a directory (not copied).
オプションなしでディレクトリは指定してはだめです。
$ cp pon chovin/
cp: pon is a directory (not copied).
cp: ./pon and pon are identical (not copied).
同じ場所に同じ名前はだめです。
$ cp -r pon .
cp: ./pon and pon are identical (not copied).
オプションの -r
を使うのは超オススメできないので -R
を使うとシンボリックリンクもコピーできる
# -rでも使える
$ cp -r pon chovin
# コピーできたように見えるけどシンボリックリンクがおかしい気がする
$ find .
.
./chovin
./chovin/pon
./chovin/pon/su
./chovin/pon/su/ke
./chovin/pon/su/ke/tarou.txt
./chovin/pon/su/symbolicklink
./chovin/pon/su/symbolicklink/tarou.txt
./pon
./pon/su
./pon/su/ke
./pon/su/ke/tarou.txt
./pon/su/symbolicklink
# シンボリックリンクは残念なことに実態をコピーしてきてシンボリックリンクじゃなくなる
$ ls -lR
# <省略>
./chovin/pon/su:
total 0
drwxr-xr-x 3 mana staff 96 12 27 16:27 ke
drwxr-xr-x 3 mana staff 96 12 27 16:27 symbolicklink
./chovin/pon/su/ke:
total 0
-rw-r--r-- 1 mana staff 0 12 27 16:27 tarou.txt
./chovin/pon/su/symbolicklink:
total 0
-rw-r--r-- 1 mana staff 0 12 27 16:27 tarou.txt
# <省略>
./pon/su:
total 0
drwxr-xr-x 3 mana staff 96 12 27 14:47 ke
lrwxr-xr-x 1 mana staff 32 12 27 16:20 symbolicklink -> /Users/mana/Downloads/pon/su/ke/
# <省略>
manに「cp -rは使うな」と書いてあった話 - 西尾泰和のはてなダイアリー
Mac で cp を使うときの注意 - tkuchikiの日記
COMPATIBILITY(互換性)
Historic versions of the cp utility had a -r option. This implementation(実装) supports that option;
however, its use is strongly discouraged(勧められない), as it does not correctly copy special files, symbolic
links, or fifo`s.
DESCRIPTION
-R If source_file designates(指定する) a directory, cp copies the directory and the entire subtree con-
nected at that point. If the source_file ends in a /, the contents of the directory are
copied rather than the directory itself. This option also causes symbolic links to be
copied, rather than indirected(間接的な) through, and for cp to create special files rather than
copying them as normal files. Created directories have the same mode as the corresponding
source directory, unmodified by the process` umask.
In -R mode, cp will continue copying even if errors are detected.
Note that cp copies hard-linked files as separate files. If you need to preserve hard
links, consider using tar(1), cpio(1), or pax(1) instead.
コピーされた階層が思ったのと違う! /
の有無で構成は変わります
「両方につける」「コピー元だけにつける」とサブディレクトリがサブディレクトリとしてコピーされる
$ cp -R pon/ chovin/
$ find .
.
./chovin
./chovin/su
./chovin/su/ke
./chovin/su/ke/tarou.txt
./chovin/su/symbolicklink
./pon
./pon/su
./pon/su/ke
./pon/su/ke/tarou.txt
./pon/su/symbolicklink
$ rm -rf chovin/*
$ cp -R pon/ chovin
$ find .
.
./chovin
./chovin/su
./chovin/su/ke
./chovin/su/ke/tarou.txt
./chovin/su/symbolicklink
./pon
./pon/su
./pon/su/ke
./pon/su/ke/tarou.txt
./pon/su/symbolicklink
「両方につけない」「コピー先だけにつける」とディレクトリがサブディレクトリとしてコピーされる
$ cp -R pon chovin
$ find .
.
./chovin
./chovin/pon
./chovin/pon/su
./chovin/pon/su/ke
./chovin/pon/su/ke/tarou.txt
./chovin/pon/su/symbolicklink
./pon
./pon/su
./pon/su/ke
./pon/su/ke/tarou.txt
./pon/su/symbolicklink
$ rm -rf chovin/*
$ cp -R pon chovin/
$ find .
.
./chovin
./chovin/pon
./chovin/pon/su
./chovin/pon/su/ke
./chovin/pon/su/ke/tarou.txt
./chovin/pon/su/symbolicklink
./pon
./pon/su
./pon/su/ke
./pon/su/ke/tarou.txt
./pon/su/symbolicklink
cp: cannot overwrite directory chovin/pon/su/symbolicklink with non-directory pon/su/symbolicklink
シンボリックリンクは上書きできません、とはいえ他のものはコピーできています。
$ cp -R pon chovin
cp: cannot overwrite directory chovin/pon/su/symbolicklink with non-directory pon/su/symbolicklink
# コピー元のファイルを追加します。
$ echo -n > pon/tyan.txt
$ find pon
pon
pon/tyan.txt
pon/su
pon/su/ke
pon/su/ke/tarou.txt
pon/su/symbolicklink
# 警告は出てもちゃんとコピーできています。
$ cp -R pon chovin
cp: cannot overwrite directory chovin/pon/su/symbolicklink with non-directory pon/su/symbolicklink
$ find chovin
chovin
chovin/pon
chovin/pon/tyan.txt
chovin/pon/su
chovin/pon/su/ke
chovin/pon/su/ke/tarou.txt
chovin/pon/su/symbolicklink