为什么Unix mv程序不需要目录的-R(递归)选项,而cp却需要它?


58

我总是在需要使用时感到困惑,cp或者mv:“ -R使用dir时需要选项吗?” 在GNU中,coreutils cp确实需要-R并且mv不需要。

我只是找不到任何理由为什么cp需要-R复制目录并mv没有。我认为,cp荷兰国际集团迪尔斯没有-R(但递归表现像有-R和喜欢的mv一样)不会引起除了打破该工具的使用人的使用习惯的任何问题。

你知道什么解释吗?可能是很久以前的原因了吗?


附加问题:为什么coreutils开发人员cp默认不递归制作复制目录?

Answers:


45

目录(从概念上来说)是一个特殊的“文件”,其中包含名称列表,以及这些名称所指向的索引节点编号。一些名称可以是子目录。有一个..指向父目录的特殊条目。

因此,很明显,更改文件名很容易:您只需更改目录条目中的名称,就没有其他了。这可以确定文件实际上是文件还是用于存储另一个目录内容的“文件”。实际上,同一个rename系统调用会同时执行这两个操作。

但是,复制的操作要简单得多。您可以只复制目录“ file”,但是您将拥有两个目录,其中文件是相同的(它们是硬链接)。如果您有一个系统,它允许到目录的硬链接,那是可以的,但是由于没有现代系统允许这样做,至少到非根目录,您必须为每个子目录进行复制。您实际上可以cp使用cp -lR-l来要求这种行为,以进行硬链接和-R递归。

但是让所有内容保持链接可能不是您想要的。而是要cp复制每个文件。这是一个相当昂贵的操作:每个文件必须读入内存,然后在第二个位置写回到磁盘。实际上,它需要几个系统调用才能打开,读取,写入和关闭文件,并且每个文件都必须重复执行。

传统文件系统也在磁盘上以这种方式工作。除了单独浏览每个文件并进行复制外,没有任何方法可以复制一堆文件,而这些是设计基本命令行实用程序时使用的文件系统类型。


mv从一个文件系统荷兰国际集团到另一个相同的“刚改名字的目录项”?
rslnx 2012年

5
否,跨文件系统与复制+删除相同(实际上,rename跨文件系统的syscall将失败)。从历史上不确定,是否mv支持交叉fs动作。
derobert

9
我可以从直接经验而不是推测中告诉您,经典mv不支持跨设备移动。它过去只是尝试尝试a rename()并在失败时显示错误消息。我仍然记得我第一次不小心使用新功能时的震惊感。为什么这个MV花这么长时间?哦,它正在执行我不打算做的递归复制!
艾伦·库里

5
@RuslanKhusnullin常用命令的命令行选项很难更改,因为它们在shell脚本中使用。可能取决于当前cp的“拒绝复制目录”行为。尽管您可以看到,cross-fs的东西可能被认为不太可能造成损坏,但仍然让Alan感到惊讶。
derobert

1
@derobert,它没有(跨文件系统mv仅适用于VAX上BSD 4.2上的单个文件)。
vonbrand

21

让我首先问另一个问题:

cp和之间有什么区别cp -R

好吧,没有-R标记,只能复制文件,因为有人非递归地复制目录是很不寻常的:非递归副本只会导致该目录的第二个名称,直接指向同一目录结构体。因为这几乎不是人们想要的,并且实际上有一个单独的程序可以执行此操作(ln),所以不允许目录的非递归副本。

mv和之间的区别是mv -R什么?

mv a b只需重命名目录中的单个条目,因此,如果mv编辑了目录,其内容也会自动移动。从这个意义上说,mv已经提供了递归属性,即重命名目录中所有条目(例如from a/1到)的“重新命名” b/1。一个mv不执行此操作的人,即将目录重命名ab,但保持a/1a/1,这并不是人们在提及移动某物时所理解的:移动橱柜时,橱柜的内容也会随之移动。移动目录而不包含目录的其他操作也已可用,称为mkdir


2
这是正确的,我只是在想cp,并mv作为操作它们被命名为:“进行复印”和“移动”。因此,如果我想复制一杯咖啡,我希望再喝一杯相同填充量的咖啡(咖啡饮料)。问题在于这些工具不是针对“普通人”的,而是针对那些了解磁盘和文件系统结构的书呆子,而不是针对诸如文件和文件目录之类的虚拟实体的。
rslnx 2012年

1
结构合理,反应合理。
12

1
@RuslanKhusnullin你的咖啡类比工程cpmv太-它不要求“nerdness”来理解,只是基本的常识的任何水平。一杯咖啡的真实副本不是空杯子-您必须递归地不仅复制杯子,还复制所有内容(咖啡)。但是,当您移动一杯咖啡时,不必分别移动其中的内容-内容随容器自然移动。
jw013 2013年

1
@ jw013您给我留下了深刻的印象,“当您移动一杯咖啡时,您不必分别移动其中的内容”,这真的很有意义,谢谢。但这是另一层抽象。我认为您的意思是“将文件作为索引节点处理”,而我想到的是类似字节序列的文件,而没有元信息。
rslnx

6

通常,当我对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用于复制文件树对于理解和编写脚本非常方便。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.