假设我们位于一个空白目录中。然后,执行以下命令:
mkdir dir1
cp -r dir1 dir2
产生两个(空白)目录dir1
和dir2
,其中dir2
已创建为 的副本dir1
。但是,如果我们这样做:
mkdir dir1
mkdir dir2
cp -r dir1 dir2
然后我们反而发现dir1
现在已经被放入了里面dir2
。这意味着完全相同的cp
命令的行为有所不同,具体取决于目标目录是否存在。如果是,则该cp
命令执行的操作与此相同:
mkdir dir1
mkdir dir2
cp -r dir1 dir2/.
这对我来说似乎非常违反直觉。我预计cp -r dir1 dir2
(当dir2
已经存在时)会删除现有的dir2
(和任何内容)并将其替换为,因为这是用于两个文件dir1
时的行为。cp
我知道递归副本本身有点不同,因为 Linux 中目录的存在方式(更广泛地在类 Unix 系统中),但我正在寻找更多解释为什么选择了这种行为。如果您能向我指出一种确保cp
其行为符合我预期的方法(无需事先测试并删除目标目录),那就加分了。我尝试了几个cp
选项,但没有任何运气。我想我会rsync
为了其他不知道该命令的人而接受解决方案。
如果这种行为不是普遍的,我在 CentOS 上使用 bash。
答案1
您正在寻找的行为是特例:
cp -R [-H|-L|-P] [-fip] source_file... target
[This] 形式由两个或多个指定了 -R 选项的操作数表示。 cp 实用程序应将每个 source_file 中的文件层次结构中的每个文件复制到名为如下的目标路径:
- 如果 target 存在并命名现有目录,则文件层次结构中每个文件的相应目标路径的名称应为 target、单个
<slash>
字符(如果 target 不以 结尾<slash>
)和文件相对于该目录的路径名的串联。包含 source_file 的目录。- 如果target不存在,且指定了两个操作数,则source_file对应的目标路径名称为target;文件层次结构中所有其他文件的相应目标路径的名称应是目标、字符
<slash>
和相对于 source_file 的文件路径名的串联。如果目标不存在并且指定了两个以上的操作数,则应发生错误...
因此我想说这是不可能做cp
你想做的事。
由于您的预期行为是“ cp -r dir1 dir2
(当dir2
已经存在时)将删除现有的dir2
(和任何内容)并将其替换为dir1
”:
rm -rf dir2 && cp -r dir1 dir2
您甚至不需要检查是否dir2
存在。
解决方案是在源中rsync
添加尾随,这样它就不会将自身复制到,而是将to的内容复制到(它仍将现有文件保留在 中):/
dir1
dir2
dir1
dir2
dir2
$ tree dir*
dir1
└── test.txt
dir2
└── test2.txt
0 directories, 2 file
$ rsync -a dir1/ dir2
$ tree dir*
dir1
└── test.txt
dir2
└── test.txt
└── test2.txt
0 directories, 3 files
$ rm -r dir2
$ rsync -a dir1/ dir2
$ tree dir*
dir1
└── test.txt
dir2
└── test.txt
0 directories, 2 files
答案2
cp 有几种形式:
cp [OPTION]... [-T] SOURCE DEST
cp [OPTION]... SOURCE... DIRECTORY
cp [OPTION]... -t DIRECTORY SOURCE...
当您这样做时,cp -r dir1 dir2
您期望对第二个参数进行隐式评估。
- 如果第二个参数是文件系统中不存在的名称,cp 会将其解释为 DEST 并创建它,copyind dir1作为目录2。
- 如果它已经存在,它将被解释为目录,从而复制 dir1进入它。
如果您不确定初始状态,并且想避免可能的多重解释,您可以简单地使用选项显式它-T
:
$ tree dir*
dir1
└── test.txt
dir2
└── test2.txt
0 directories, 2 file
$ cp -r dir1 -T dir2
$ tree dir*
dir1
└── test.txt
dir2
└── test.txt
0 directories, 3 files
$ rm -r dir2
$ cp -r dir1 -T dir2
$ tree dir*
dir1
└── test.txt
dir2
└── test.txt
0 directories, 2 files