GNU cp 和 mv 中 -T 选项的附加值是什么?

GNU cp 和 mv 中 -T 选项的附加值是什么?

为什么某些 GNU Coreutils 命令有该-T/--no-target-directory选项?看起来它所做的一切都可以使用.传统 Unix 目录层次结构中的 (self dot) 语义来实现。

考虑到:

cp -rT /this/source dir

-T选项可防止副本创建dir/source子目录。相反,内容/this/source被识别并且相应地在树之间映射。dir例如,/this/source/foo.cgo todir/foo.c等等,而不是 to dir/source/foo.c

但这可以轻松完成,无需-T使用以下选项:

cp -r /this/source/. dir  # Probably worked fine since dawn of Unix?

从语义上讲,尾随点组件被复制为 的子级dir,但当然该“子级”已经存在(因此不必创建)并且实际上是dir其本身,因此效果是/this/path用 标识dir

如果当前目录是目标,则效果很好:

cp -r /this/tree/node/. . # node's children go to current dir

有什么你可以做的吗仅有的可以-T合理化它的存在吗? (除了支持不实现点目录的操作系统之外,文档中没有提到其基本原理。)

上面的点技巧是否不能解决 GNU Info 文档中提到的相同竞争条件-T

答案1

您的.技巧只能在复制目录而不是文件时使用。该-T选项适用于目录和文件。如果你这样做:

cp srcfile destfile

并且已经有一个名为destfileit 的目录将复制到destfile/srcfile,这可能不是有意的。所以你用

cp -T srcfile destfile

并且您正确地得到了错误:

cp: cannot overwrite directory `destfile' with non-directory

如果您尝试使用该.方法,则副本将永远无法工作:

cp: cannot stat `srcfile/.`: Not a directory

答案2

cp//最初设计时的问题是它们是两个命令mv合而为一(ln复制到复制到)。

cp A B

或者是复制A到B或者将A复制到B中将A复制到B/A)取决于是否B存在并且是否是目录(如果 B 是目录的符号链接,则有更多变化)。

这很糟糕,因为它含糊不清。因此 GNU 实现添加了选项来解决这个问题。

cp -T A B

将 A 复制到 B不管。如果B存在并且是一个目录,则会失败(除非您通过-r)。无论如何,当您打算复制时,您最终不会得到A里面的文件BAB.

和:

cp -t B A

是个复制到

答案3

-T如果目标文件的目录不正确地存在,则可能会导致失败:

$ mkdir mustbeafile
$ touch afile
$ cp -T afile mustbeafile
cp: cannot overwrite directory `mustbeafile' with non-directory
$ echo $?
1
$ cp afile mustbeafile
$ 

也就是说,不是成功地意外复制到子目录,而是出现警告和不好的退出状态,这可能会导致脚本中止,并且人工检查为什么存在不应该存在的目录成为一体。

答案4

当在脚本中使用命令而不是手动输入命令时,使用标志也更清晰,并且产生意外影响的风险更小。将点修补到脚本中的路径上可能会导致各种意想不到的恶作剧。

相关内容