cp的行为奇怪。(点)或..(点)是源目录


15

这个答案表明,可以将目录中的所有文件(包括隐藏文件)复制src到目录中,dest如下所示:

mkdir dest
cp -r src/. dest

答案或其注释中没有任何解释说明其为何真正起作用,并且似乎也没有人找到相关文档。

我尝试了几件事。一,正常情况:

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src dest
$ ls -A dest
dest_file  src

然后,/.最后:

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/. dest
$ ls -A dest
dest_file  .dotfile  src_dir  src_file

因此,它的行为与相似*,但也会复制隐藏的文件。

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/* dest
$ ls -A dest
dest_file  src_dir  src_file

...有适当的硬链接作为这里解释,就像目录条目本身。

这种行为从何而来,在哪里得到记录?


3
你是什​​么意思,没人能找到文件?该cp参考资料清楚地说明了cp -R工作原理。.并且..是目录就像任何其他目录,没有什么神奇或神秘的他们。
AlexP

2
@AlexP我编辑了答案以使其更清楚。整点是,...不表现得像其他目录。
iFreilicht

我试图解释为什么它可以工作在如何使用cp以幂等方式递归复制文件夹的情况下
roaima

Answers:


27

该行为是针对的已记录算法的逻辑结果cp -R。参见POSIX,步骤2f:

必须将目录source_file中的文件复制到目录dest_file,并按照此处列出的四个步骤(1到4)将文件作为source_files

...是目录,分别是当前目录和父目录。就外壳而言,它们都不是特殊的,因此扩展也不关心它们,并且将复制目录(包括隐藏文件)。*另一方面,将扩展为文件列表,这是过滤掉隐藏文件的位置。

src/.是内部的当前目录src,它src本身是;src/src_dir/..src_dir的父目录,又是src。因此,从外部看src,如果src是目录,则指定src/.src/src_dir/..作为源文件cp是等效的,然后复制的内容src,包括隐藏文件。

指定的要点src/.是,如果src不是目录(或目录的符号链接),它将失败,而src如果不是目录,则失败。它还将src仅复制内容,而不复制src自身。这也与文档匹配:

如果目标存在并命名现有目录,则文件层次结构中每个文件的对应目标路径的名称应为目标的串联,如果目标未以斜杠结尾则为单个斜杠字符,并且文件的相对路径名应为到包含source_file的目录。

因此,cp -R src/. dest将的内容复制srcdest/.(源文件.在中src),而cp -R src dest将的内容复制srcdest/src(源文件在中src)。

另一种思考的方式是比较复制src/src_dirsrc/.,而不是比较src/.src.行为src_dir与前一种情况相同。


但是它的行为方式不同。指定src将目录复制到中destsrc/.将复制内容。我会尽力使这个问题更清楚。
iFreilicht

在那里,我认为这可以回答您的基本问题。
斯蒂芬·基特

1
@StéphaneOP比较复制src/.src/*(注意,不是 src/.*);src/*如果全局忽略它们,则不包括隐藏文件...
Stephen Kitt

1
嗯,“包含source_file的目录”。好吧,显然src包含,src/.但这确实意味着目录的包含目录取决于您如何命名目录。当然,.链接的存在以某种方式意味着所有目录都包含它们自己,但是对于所有人而言可能并不直观。除了这种行为之外,还可能会想当然地假定“包含目录的目录foo”将由确定foo/..,在这种情况下,我们引用foo还是没有关系foo/.:结果包含目录将是相同的。
ilkkachu

1
这是说,之间的区别foo,并foo/.似乎有点微妙,但我不介意,我也觉得稍微会哄。
ilkkachu

1

当你跑步时cp -R src/foo dest,你会得到dest/foo。因此,如果目录dest/foo不存在,cp将创建它,然后将的内容复制src/foodest/foo

运行时cp -R src/. destcp看到dest/.存在,然后只需复制src/.to 的内容即可dest/.

当您将其视为复制.从中命名的目录src并将其内容与现有目录合并时dest/.,这将很有意义。

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.