考虑以下:
/tmp$ mkdir -p src/{a,b} dst/dstsub; touch src/{a,b}/hello
/tmp$ tree src/ dst/
src/
├── a
│ └── hello
└── b
└── hello
dst/
└── dstsub
现在运行
/tmp$ cp -r src/a/.. dst/dstsub/
src
使用 GNU cp,这会导致==的内容src/a/..
被复制到 中dst/dstsub
,如下所示:
/tmp$ tree dst/
dst/
└── dstsub
├── a
│ └── hello
└── b
└── hello
然而,使用 Busybox 重复该练习会产生不同的目标结构:
/tmp$ rm -r dst/; mkdir -p dst/dstsub
/tmp$ busybox cp -r src/a/.. dst/dstsub/
/tmp$ tree dst/
dst/
├── a
│ └── hello
├── b
│ └── hello
└── dstsub
src
这里,源目录==的内容src/a/..
被复制了旁边目标目录dst/dstsub/
,而不是在它。
尝试阅读标准文本:
cp -R [-H|-L|-P] [-fip] source_file... target
[...] cp 实用程序应复制以每个文件为根的文件层次结构中的每个文件。源文件到名为如下的目标路径:
如果目标存在并命名一个现有目录,文件层次结构中每个文件的相应目标路径的名称应为串联目标, 单个<斜杠>字符如果目标并没有结束于<斜杠>,以及文件相对于包含的目录的路径名源文件。
目标is dst/dstsub/
,它是一个现有目录,以斜杠结尾。源文件is src/a/..
,因此包含它的目录是src/a/
以及相对于包含它的目录的路径名是等../a
,../b
这将导致目标路径等dst/dstsub/../a
,dst/dstsub/../b
与 Busybox 的行为相匹配。
但是,如果我们首先规范化要删除的源路径..
,那么它将是src/
(或者更确切地说src/.
,因为行为是src
其本身不会被复制,就像cp -r src dst
创建时会发生的那样dst/src
)。这将导致诸如dst/dstsub/./a
等的目标路径,这似乎与 GNU cp 的作用相匹配。 (我不知道它是否确实如此,但这似乎是一个合理的解释。)
唯一提到的是..
(点对点)很特别,我在标准文本中看到的是:
2.如果源文件如果是目录类型,则需要执行以下步骤:
b.如果源文件未指定为操作数并且源文件是点或者点对点, cp 不再做任何事情源文件并继续处理任何剩余的文件。
这并不适用,因为包含的路径..
是作为命令行操作数显式给出的。另外,操作数并不完全是..
为了以防万一,但我在 GNU 和 Busybox 上都得到了与..
源目录相同的结果:
/tmp$ cd src/a/
/tmp/src/a$ cp -r .. /tmp/dst/dstsub/
..
标准是否允许上述(或等效行为)的规范化?应该做吗?应该是不是做完了?或者关于 GNU cp 的行为或标准文本的解释我还错过了什么吗?