为什么“mv”不需要“-r”来处理目录,但“rm”和“cp”需要?

alw*_*938 32 linux command-line

我正在学习基本的 Linux 命令。这似乎违反直觉:为什么复制(cp)和删除(rm)需要递归选项(-R, --recursive)来与目录交互,而移动(mv)已经不需要这样做了?

小智 62

从目录的基本角度来看:

  • rm必须递归到目录并为每个文件和目录调用unlinkandrmdir
  • cp必须递归到目录中进行读取,然后将每个文件和目录重写到新位置
  • mv只需要进行一次调用rename

由于没有要mv为目录实现的递归操作,因此它没有选项-r

与其他专注于损坏或所花费时间的答案不同,rm实际cp原因是它只是这些命令的实现的泄漏抽象。

  • 这是有道理的,直到人们意识到到另一个文件系统的“mv”是“cp”+“rm”。可能“mv -r”不是一个东西,因为我们不想向用户公开内部机制。如果是单个文件系统,您的推理成立,“mv”不需要“-r”。我的猜测是:如果移动到另一个文件系统,我们希望“mv”在以完全相同的方式调用时完成预期的工作。 (15认同)
  • 我很确定跨文件系统 mv 是很晚才出现的东西。 (14认同)
  • @plugwash AB 链接到 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html#tag_20_82_18 描述了 _2018_ 中对 POSIX 标准的补充。所以是的,比原来的“mv”晚了很多(尽管在 2018 年之前确实存在非标准实现)。 (3认同)
  • 标准的添加只是意味着“mv”是“必需的”,以允许跨文件系统重命名兼容,而不是说“mv”之前没有该功能。一旦某个功能被证明足够常见或流行,它可能会被添加到标准中,以便让坚持者也实现该功能:)(例如,我相信数组旨在添加到 POSIX shell 规范中现在的日子。) (2认同)

Rob*_*son 39

  • rm(删除又名删除):破坏信息,因此如果您在目录上运行它而您打算在文件上运行它,那么您可能会造成很大的损害。
  • cp(复制):再说一遍,您的意思是复制文件吗?如果我们复制一个目录,其中可能有数千个文件。这可能不是您想要的,并且填满磁盘是不好的。
  • mv(移动又名重命名):仅重命名目录,其内容始终保持不变,因此我们在这里无法进行递归操作。我们当然不想将目录及其所有子目录重命名为相同的名称。

  • 对于 mv,我不确定文件系统是如何工作的,但是如果它只是更改地址(例如更改指针)并且不需要执行任何递归操作,那么我认为这就是为什么它不需要 -R 的原因,因为您不需要除了完整路径的属性之外,还可以更改子文件夹/文件指针,但这可能是在事后计算的。我想这可能更多是一个文件库问题。 (8认同)
  • @Robert我基本上同意你的观点,但仍然存在一个小小的不一致:当“mv”的源和目标位于不同的文件系统上时,幕后发生的事情是“cp”+“rm”。不过,“-r”不是必需的。 (4认同)
  • @PierU 找到足够旧的 mv 版本,您将收到 EXDEV(无效的跨设备链接)错误。较新的版本只是通过像 cp+rm 那样的行为来处理此错误。POSIX1.2017 中解释了其原理:https://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html#tag_20_82_18 “没有 -R 选项来确认移动目录实际上是有意的,因为这样的在历史实践中移动目录不需要选项。有时要求应用程序根据目的地指定它,似乎也不一致。” (4认同)
  • 我不相信这个解释。`rm` 和 `mv` 具有相同的破坏潜力,如果您将文件 X 复制到文件 Y 上,您就会丢失文件 Y。至少当您输入 `rm` 时,您肯定是想破坏某些东西。如果您不小心复制了大量数据,您始终可以在进程创建过多数据之前终止该进程。@Anon 的答案更合理。 (4认同)
  • 需要注意的是`mv`可以删除数据。事实上,它可以删除用户刚刚写入磁盘的数据!维护者拒绝承认这是一个错误,但基本上重现它的方法是将目录移动到不同的文件系统,并在移动数据时将新文件添加到该目录(或其任何子目录) 。在移动过程终止后,该文件是否仍然存在于任何文件系统上就变成了运气问题。它甚至不会打印警告,通知您它刚刚删除了您的数据。 (3认同)
  • @Clumsycat:“mv”和“rm”具有同等的破坏单个文件的潜力,但只有“rm”可以破坏整个目录树。在同一文件系统中,在失败的“rename(dir1, dir2)”系统调用然后成功的“opendir”/“renameat”系统调用之后,“mv dir1 dir2”会留下“dir2/dir1”。不过,我同意潜在的损害似乎并不是最直接的解释,并且同意阿农的答案更好,约翰·达尔曼的新答案也是如此。 (2认同)

Joh*_*man 6

通过一些有关文件系统如何工作的信息,这更有意义。

目录实际上是一种文件类型。其内容是该目录中文件的名称以及有关在磁盘上何处找到它们的信息。该信息存储在磁盘上,而不是目录中。

当您mv移动目录时,您只是移动目录本身。文件完全保留在原来的位置,并且没有对它们进行任何操作。因此,无需递归到目录中。其中的文件自然而自动地随之“移动”。

是的,如果您在磁盘之间移动内容,情况会更复杂。这些命令主要是为简单的情况而设计的,并且在幕后有额外的机制来处理复杂的情况。