Linux拷贝命令cp的一点总结(附cannot overwrite directory xxx with non-directory)

昨天验证一个补丁,补丁是以old/new形式给出的,需要自行合入到代码工程中去,得到建议说可以把new文件夹中的东西拷贝到工程中即可,但对比了new文件夹与工程中对应文件夹的内容,涉及到三方面

1.new文件夹中有新增的独有文件

2.new文件夹与工程同名代码部分需要覆盖

3.原工程文件夹独有的文件需要保留

忽然一下没了头绪,因为发给客户的补丁不能出错,怕自己对比来对比去最终晕头转向,又得到建议可以在linux下用cp -r命令,虽然用惯了cp -r,但是都是往空白处拷贝,潜意识认为cp -r命令会覆盖整个目标,但是结果并不是如此

由此模拟了一个简单的场景,看看cp -r到底是什么行为

先把cp的选项罗列如下:

-a:此参数的效果和同时指定"-dpR"参数相同;
-d:当复制符号连接时,把目标文件或目录也建立为符号连接,并指向与源文件或目录连接的原始文件或目录;
-f:强行复制文件或目录,不论目标文件或目录是否已存在;
-i:覆盖既有文件之前先询问用户;
-l:对源文件建立硬连接,而非复制文件;
-p:保留源文件或目录的属性;
-R/r:递归处理,将指定目录下的所有文件与子目录一并处理;
-s:对源文件建立符号连接,而非复制文件;
-u:使用这项参数后只会在源文件的更改时间较目标文件更新时或是名称相互对应的目标文件并不存在时,才复制文件;
-S:在备份文件时,用指定的后缀“SUFFIX”代替文件的默认后缀;
-b:覆盖已存在的文件目标前将目标文件备份;
-v:详细显示命令执行的操作。

自建场景如下:

两个文件夹source和dest

----------------------------------------------------------

source中有两个文件夹:one和two

one中有文件1.txt(内容为source:1.txt); one中有文件1_source.txt(内容为1_source.txt)

two中有文件2.txt(内容为source:2.txt); two中有文件2_source.txt(内容为2_source.txt)

-----------------------------------------------------------

dest中有三个文件夹:one two three

one中有文件1.txt(内容为dest:1.txt); one中有文件1_dest.txt(内容为1_dest.txt)

two中有文件2.txt(内容为dest:2.txt); two中有文件2_dest.txt(内容为2_dest.txt)

three中有文件3.txt(内容为dest:3.txt)

BEFORE:

root@ubuntu:/shiyan/shiyan291# ls
dest  source
root@ubuntu:/shiyan/shiyan291# cd source
root@ubuntu:/shiyan/shiyan291/source# ls
one  two
root@ubuntu:/shiyan/shiyan291/source# cd one
root@ubuntu:/shiyan/shiyan291/source/one# ls
1_source.txt  1.txt
root@ubuntu:/shiyan/shiyan291/source/one# cat 1.txt
source:1.txt
root@ubuntu:/shiyan/shiyan291/source/one# cat 1_source.txt 
1_source.txt
root@ubuntu:/shiyan/shiyan291/source/one# cd ../
root@ubuntu:/shiyan/shiyan291/source# ls
one  two
root@ubuntu:/shiyan/shiyan291/source# cd two
root@ubuntu:/shiyan/shiyan291/source/two# ls
2_source.txt  2.txt
root@ubuntu:/shiyan/shiyan291/source/two# cat 2.txt
source:2.txt
root@ubuntu:/shiyan/shiyan291/source/two# cat 2_source.txt 
2_source.txt
root@ubuntu:/shiyan/shiyan291/source/two# cd ../
root@ubuntu:/shiyan/shiyan291/source# ls
one  two
root@ubuntu:/shiyan/shiyan291/source# cd ../
root@ubuntu:/shiyan/shiyan291# ls
dest  source
root@ubuntu:/shiyan/shiyan291# cd dest
root@ubuntu:/shiyan/shiyan291/dest# ls
one  three  two
root@ubuntu:/shiyan/shiyan291/dest# cd one
root@ubuntu:/shiyan/shiyan291/dest/one# ls
1_dest.txt  1.txt
root@ubuntu:/shiyan/shiyan291/dest/one# cat 1.txt
dest:1.txt
root@ubuntu:/shiyan/shiyan291/dest/one# cat 1_dest.txt 
1_dest.txt
root@ubuntu:/shiyan/shiyan291/dest/one# cd ../
root@ubuntu:/shiyan/shiyan291/dest# ls
one  three  two
root@ubuntu:/shiyan/shiyan291/dest# cd two
root@ubuntu:/shiyan/shiyan291/dest/two# ls
2_dest.txt  2.txt
root@ubuntu:/shiyan/shiyan291/dest/two# cat 2.txt
dest:2.txt
root@ubuntu:/shiyan/shiyan291/dest/two# cat 2_dest.txt 
2_dest.txt
root@ubuntu:/shiyan/shiyan291/dest/two# cd ../
root@ubuntu:/shiyan/shiyan291/dest# ls
one  three  two
root@ubuntu:/shiyan/shiyan291/dest# cd three
root@ubuntu:/shiyan/shiyan291/dest/three# ls
3.txt
root@ubuntu:/shiyan/shiyan291/dest/three# cat 3.txt
dest:3.txt
root@ubuntu:/shiyan/shiyan291/dest/three# 
root@ubuntu:/shiyan/shiyan291/dest/three# 
root@ubuntu:/shiyan/shiyan291/dest/three# 
root@ubuntu:/shiyan/shiyan291/dest/three# 

当我们将source中的one two文件夹用cp -r命令拷贝到dest文件夹时,会完全覆盖dest吗?会完全覆盖dest的one two吗?

root@ubuntu:/shiyan/shiyan291# ls
dest  source
root@ubuntu:/shiyan/shiyan291# cd source
root@ubuntu:/shiyan/shiyan291/source# ls
one  two
root@ubuntu:/shiyan/shiyan291/source# cp -ri ./* ../
dest/   source/ 
root@ubuntu:/shiyan/shiyan291/source# cp -ri ./* ../dest/
cp:是否覆盖"../dest/one/1.txt"? y
cp:是否覆盖"../dest/two/2.txt"? y
root@ubuntu:/shiyan/shiyan291/source# 

AFTER:

root@ubuntu:/shiyan/shiyan291# ls
dest  source
root@ubuntu:/shiyan/shiyan291# cd dest
root@ubuntu:/shiyan/shiyan291/dest# ls
one  three  two
root@ubuntu:/shiyan/shiyan291/dest# cd one
root@ubuntu:/shiyan/shiyan291/dest/one# ls
1_dest.txt  1_source.txt  1.txt
root@ubuntu:/shiyan/shiyan291/dest/one# cat 1.txt
source:1.txt
root@ubuntu:/shiyan/shiyan291/dest/one# cat 1_source.txt 
1_source.txt
root@ubuntu:/shiyan/shiyan291/dest/one# cat 1_dest.txt 
1_dest.txt
root@ubuntu:/shiyan/shiyan291/dest/one# cd ../
root@ubuntu:/shiyan/shiyan291/dest# ls
one  three  two
root@ubuntu:/shiyan/shiyan291/dest# cd two
root@ubuntu:/shiyan/shiyan291/dest/two# ls
2_dest.txt  2_source.txt  2.txt
root@ubuntu:/shiyan/shiyan291/dest/two# cat 2.txt
source:2.txt
root@ubuntu:/shiyan/shiyan291/dest/two# cat 2_source.txt 
2_source.txt
root@ubuntu:/shiyan/shiyan291/dest/two# cat 2_dest.txt 
2_dest.txt
root@ubuntu:/shiyan/shiyan291/dest/two# cd ../
root@ubuntu:/shiyan/shiyan291/dest# ls
one  three  two
root@ubuntu:/shiyan/shiyan291/dest# cd three
root@ubuntu:/shiyan/shiyan291/dest/three# ls
3.txt
root@ubuntu:/shiyan/shiyan291/dest/three# cat 3.txt
dest:3.txt
root@ubuntu:/shiyan/shiyan291/dest/three# 
root@ubuntu:/shiyan/shiyan291/dest/three# 
root@ubuntu:/shiyan/shiyan291/dest/three# 

【注意与结论】:

可以看到在我设计的场景下,dest中独有的文件夹/文件被保留,source中独有的文件/文件夹被拷贝,source与dest同名的文件则会被覆盖,这一点可以根据-i交互式选项看出,因为只问了1.txt与2.txt是否被覆盖

最后我想吐槽一点:做技术这一行大家都不容易,谁也不是一开始什么都知道,技术很牛逼的人也不是什么都知道完了,有些技术很好的人往往不屑于他们觉得的很简单的问题,往往出口伤人,我觉得这是不对的,应该谦逊待人,自己也有成长,共勉

【诈尸更新】:

最近又在用cp命令的Makefile中遇到了如下问题:

cannot overwrite directory xxx with non-directory,一时都不知道是为什么

因为是两个目录对拷,所以自认为不会出现问题,结果就是因为源在linux下居然是个link文件,导致错误的发生,自己复现了场景,构建如下:(注意我们在这里用的cp -af,可以保证文件的链接,权限等属性)

src目录:文件1和文件2.txt,des目录:目录1和文件3.txt

cp -af src/* des/会发生什么呢?发生了两件事:

(1).2.txt被拷贝到des目录下

(2).cp报错,试图用非目录去覆盖目录

所以有一点经验教训就是如果要完整拷贝的话最好先把des下的东西删干净!

root@ubuntu:/lianxi/lianxi_makefile/test# cp -af src/* des/
cp: 无法以非目录来覆盖目录"des/1"
root@ubuntu:/lianxi/lianxi_makefile/test#
root@ubuntu:/lianxi/lianxi_makefile/test/des# ls
1  2.txt  3.txt
root@ubuntu:/lianxi/lianxi_makefile/test/des# 

【转】:https://blog.csdn.net/wanghai__/article/details/5776010

你可能感兴趣的:(Linux基础,makefile)