为什么'cp -r ../* .'工作但不是“cp -r ...”

为什么'cp -r ../* .'工作但不是“cp -r ...”

如果我有树:

.
├── child
├── dir1
├── dir2
├── dir3
├── file1
├── file2
└── file3

这是在以下命令中发出这些命令的结果child:这可以工作并复制所有文件和目录:

cp -r ../* .
----
cp: cannot copy a directory, '../child', into itself, './child'

这仅复制child文件,但不复制任何目录:

cp -r .. .
----
cp: cannot copy a directory, '..', into itself, '.'

答案1

查看实际执行的命令:

$ set -x; cp -r ../* .
+ cp -r ../child ../dir1 ../dir2 ../dir3 ../file1 ../file2 ../file3 .
cp: cannot copy a directory, '../child', into itself, './child'
$ set -x; cp -r .. .
+ cp -r .. .
cp: cannot copy a directory, '..', into itself, '.'

您的两个命令都尝试将目录复制到自身中,从而导致循环。实现cp可能会检测到它,并在某个时刻停止,或者无限期地继续复制(例如,GNU 和 BusyBoxcp停止;FreeBSDcp继续复制,直到达到文件名长度限制;类似地,cp在 MacOS 上继续复制,如下所示关于 U&L 的另一个问题似乎建议)。
无论如何,递归地将目录复制到自身中最终将因错误而停止。

假设问题是关于 GNU cp(您可能在 GNU/Linux 系统上拥有的那个),一般情况下您的第二个命令(cp -r .. . ) 将复制(不可预测的?)部分的树的根部..,检测循环并因错误而停止,而不对该树中的任何内容进行任何进一步处理。

另一方面,在第一个命令 ( cp -r ../* .) 中,cp给出了八个单独的参数。虽然将child的内容复制到child失败,但其他目录和文件可以毫无问题地复制,因为它们都不包含child自身。但请注意,这在不检测循环并不断进行递归复制
的系统上不会按预期“工作” 。cp


作为更安全的方法,要将父目录的所有内容复制到当前目录(child)(不包括当前目录本身),您可以使用:

$ shopt -s nullglob dotglob extglob
$ cp -r ../!(child) .

相关内容