cp
当需要使用或mv
:“-R
使用 dir 时我需要选项吗?”时,我总是会搞砸。在 GNU coreutils 中cp
确实需要-R
也不mv
需要。
我只是找不到任何原因为什么cp
需要-R
复制目录的选项而不mv
需要。我认为cp
ing dirs without -R
(但递归地表现得像 Theres-R
和 likemv
一样)不会造成任何问题,除了打破某人使用该工具的习惯。
你知道有什么解释吗?也许很久以前就有原因了?
附加问题:cp
为什么 coreutils 开发人员默认不递归地复制目录?
答案1
目录(概念上)是一个特殊的“文件”,其中包含名称列表以及这些名称指向的索引节点号。有些名称可以是子目录。有一个特殊的条目..
指向父目录。
因此,很明显,更改文件名很容易:您只需更改目录条目中的名称即可,无需其他任何操作。它保存该文件是否实际上是一个文件,或者是一个用于存储另一个目录内容的“文件”。事实上,同一个rename
系统调用可以完成这两件事。
然而,复制是一个不那么简单的操作。你可以只需复制目录“文件”,但是您将有两个目录,其中的文件是相同的(它们是硬链接)。如果您有一个允许目录硬链接的系统,那么就可以,但由于没有现代系统允许这样做,至少对于非 root 来说,您必须为每个子目录进行该复制。实际上,您可以cp
使用 : 来请求此行为cp -lR
:-l
对于硬链接,-R
对于递归。
但将所有内容保持联系可能并不是您想要的。相反,您想要cp
复制每个文件。这是一个相当昂贵的操作:每个文件都必须读入内存,然后写回到磁盘的第二个位置。实际上需要多个系统调用来打开、读取、写入和关闭文件,并且必须对每个文件重复这些操作。
传统文件系统在磁盘上也以这种方式工作。除了单独检查每个文件并复制它之外,没有任何方法可以复制一堆文件,而这些是设计基本命令行实用程序时使用的文件系统类型。
答案2
首先让我问另一个问题:
cp
和 和有什么区别cp -R
?
好吧,如果没有该-R
标志,则只能复制文件,因为有人想要非递归地复制目录是相当不寻常的:非递归复制只会导致目录的第二个名称,直接指向同一个目录结构。因为这很少是人们想要的,并且实际上有一个单独的程序可以执行此操作(ln
),所以不允许目录的非递归副本。
mv
那么和之间有什么区别呢mv -R
?
mv a b
只是重命名目录中的单个条目,因此如果目录被mv
编辑,其内容也会自动移动。从这个意义上说,mv
已经提供了递归属性,即“重命名”重命名目录中的所有条目,例如 froma/1
到b/1
。mv
不这样做的A ,即将目录重命名a
为b
,但保留a/1
为a/1
,并不是人们在提到移动某物时所理解的:当您移动橱柜时,橱柜中的内容也会被移动。另一种操作,即移动不包含其内容的目录,也已经可用,它称为mkdir
.
答案3
通常,当我搞乱 Unix 逻辑时,我会查看 Plan9,看看 Unix 发明者如何在多年后实现相同的任务,而不坚持向后兼容性。
因此 Plan9 提供了仅操作文件的工具cp
。mv
`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
does `cp f1 f2 && rm f1` else
can rename dirs (`mv d1 d2`) but will not move dir to another dir.
对于复制目录,确实如此dircp
(@{cd fromdir && tar c .} | @{cd todir && tar xT}
rc shell 语法)
对于移动目录我认为只有dircp d1 d2 && rm -r d1
我认为这种限制cp
和mv
仅用于文件操作(而不是目录)的决定使磁盘操作更加清晰,并且用于tar
复制文件树对于理解和编写脚本来说非常舒适。