为什么 mv 实用程序不需要 -R (递归)选项,但 cp 需要?

为什么 mv 实用程序不需要 -R (递归)选项,但 cp 需要?

cp当需要使用或mv:“-R使用 dir 时我需要选项吗?”时,我总是会搞砸。在 GNU coreutils 中cp确实需要-R也不mv需要。

我只是找不到任何原因为什么cp需要-R复制目录的选项而不mv需要。我认为cping 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/1b/1mv不这样做的A ,即将目录重命名ab,但保留a/1a/1,并不是人们在提到移动某物时所理解的:当您移动橱柜时,橱柜中的内容也会被移动。另一种操作,即移动不包含其内容的目录,也已经可用,它称为mkdir.

答案3

通常,当我搞乱 Unix 逻辑时,我会查看 Plan9,看看 Unix 发明者如何在多年后实现相同的任务,而不坚持向后兼容性。

因此 Plan9 提供了仅操作文件的工具cpmv

`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

我认为这种限制cpmv仅用于文件操作(而不是目录)的决定使磁盘操作更加清晰,并且用于tar复制文件树对于理解和编写脚本来说非常舒适。

相关内容