为什么在 Linux 中复制目录时需要 -r 递归?

为什么在 Linux 中复制目录时需要 -r 递归?

-r我的问题是为什么在复制目录时需要使用(递归) 标志?即,为什么要这样做:

cp -r dir1 copyDir1

复制目录时我什么时候不希望出现这种行为?

目录的递归复制难道不是真正的“默认”行为、即我们几乎一直想要的行为吗?

感觉这是一个多余的标志。

答案1

文件系统的工作方式是,目录实际上并不是包含文件的文件夹,而是包含 inode 指针的文件与其相连的“子”文件。也就是说,从文件系统的角度来看,文件就是文件,而目录只是一个包含连接文件列表的文件。

因此从命令行角度来看,执行以下操作:

cp dir1 copyDir1

基本上意味着将名为 的文件复制dir1到名为 的新文件中copyDir1。就文件系统而言,dir1只是一个文件;只有当文件系统实际检查dir1那堆位实际上是什么时,它才是“目录”这一事实才会显现出来。

-r标志告诉文件系统递归地滚动文件/目录树并将可能是该文件“子”的任何和所有内容复制到新位置。

至于为什么这看起来是多余的或多余的,这实际上归结于处理文件系统的历史方法。以及创建一个可以避免所有类型的用户相关错误(无论是意外的还是故意的)的系统。

意思是,假设你~/bin的主目录中有一个文件想要复制但却不小心遗漏了~— — 因为你是人,会犯错误 — — 所以就像/bin这样:

cp /bin/ ~/copy_of_bin

有了目录这个“安全网”/bin以及对标志的需求,-r您就可以避免意外地将您当前系统的整个二进制根目录复制到您的主目录中。如果没有这个安全网,就会发生小灾难,也可能是大灾难。

这里的逻辑是,在 GUI(图形用户界面)出现之前,需要设置逻辑/行为惯例,以避免用户造成可能导致系统崩溃的事故。-r现在使用标志就是其中之一。

如果这看起来多余,那么只需看看可以置于 Linux 文件系统之上的现代 GUI 系统即可。GUI 通过允许用户轻松拖放文件和目录来解决此类基本用户问题。

但在基于文本的界面领域中,该领域中的许多“用户体验”基本上只是合乎逻辑和启发式的障碍,有助于控制用户,从而避免潜在的灾难。

同样,这也是为什么 Linux/Unix 文件系统默认不设置777权限和权限,以及当用户设置权限或授予所有人权限时,真正的系统管理员会感到畏缩的原因。这些都是确保系统稳定和尽可能“用户保护”的基本措施;任何急于打破这些惯例的人很可能会在不知情的情况下损坏他们的系统。sudo777sudo


附加信息: Unix Stack Exchange 网站上的另一个答案很好地解释了为什么目录的非递归复制是有问题的;重点是我的。

好吧,没有 -R 标志,就只能复制文件,因为有人想要非递归复制目录的情况相当不寻常:非递归复制只会产生目录的第二个名称,直接指向相同的目录结构。因为这很少是人们想要的,并且实际上有一个单独的程序可以执行此操作(ln),所以不允许非递归复制目录。

因此,如果目录实际上只是一个包含 inode 项目的文件,则直接复制该文件就相当于硬链接的工作方式。这不是任何人想要的。

答案2

确实,这几乎是我们一直想要的行为。但这并不意味着递归复制应该是默认行为。

我认为原因cp在于Unix 哲学. Unix 青睐以下程序专做一件事并做好它以及界面和实现都很简单(有时称为更坏就是更好)。

这里的关键部分是认识到cp不复制目录 -cp复制文件(和仅有的文件)。如果你想复制目录,cp 递归调用自身,以便复制每个目录上的文件。

当然,从用户的角度来看,“复制目录”和“递归复制文件”之间没有任何区别,但是有了这个接口可以帮助实现保持简单

如果你能够cp复制目录,你很快就会想添加更多只对目录有意义的功能 - 例如,你可能只想复制以 结尾的文件名.sh。不可避免地,这导致了膨胀功能蔓延我们在其他操作系统中习惯使用这种技术——这会使软件运行缓慢、复杂且容易出错。

另一个优点是,它还可以-r帮助用户了解界面下真正发生的事情。这样做的一个很好的副作用是,当你了解支持递归操作的其他工具(例如grep)时,学习递归操作的概念将为你省去一些工作。


有些人肯定会告诉你,向用户公开实现细节是坏的,并且拥有更多特征好的。我在这里的目的仅仅是解释这种行为的理由,所以我不会试图争论。

答案3

与目录的交互确保您知道您正在与目录交互而不是仅仅与单个文件交互。

例如:

$ tree
.
└── folder1
    └── sub1
        └── subsub1

3 directories, 0 files
$
$ cp folder1/ folder2
cp: folder1/ is a directory (not copied).
$
$ mkdir blah
$ cp blah/ blah2
cp: blah/ is a directory (not copied).
$ rm blah/
rm: blah/: is a directory

因此,如果您想成功复制一个文件夹,因为它暗示了该文件夹和与引用该文件夹相关的对象,所以您必须将其视为文件集合:

$ cp -r folder1/ folder2
$ rm -rf folder1

答案4

今天,这可能是次优的 UI,但这是在 1970 年左右设计 UNIX 时做出的决定,当时磁盘价格要昂贵得多。数百万个 shell 脚本都依赖于这种方式,现在要改变它已经太晚了。

本文了解原始设计信息。

相关内容