我的理解cp src dest
是:
- 如果
src
是一个文件并且dest
不存在,但其父目录存在,则dest
创建。 - 如果
src
是一个文件并且dest
是一个文件,dest
则被 的内容覆盖src
。 - 如果
src
是文件且dest
是目录,dest/src
则创建。
我正在努力避免情况#3。如果我编写一个脚本假设dest
惯于是一个目录,但在运行时发现它是,我不想cp
把文件放在错误的地方然后默默地继续。
相反,我希望它:
- 删除整个
dest
目录并将其替换为所需的文件。 - 不执行任何操作就出错。
我也希望这能够原子地发生。使用单独的命令(例如test -d
检查是否dest
是目录)可能会出现 TOCTTOU 问题。
这可以用 来完成吗cp
?如果没有,可以使用其他类似的普遍命令来完成吗?
我对便携式解决方案和依赖非标准扩展的解决方案都感兴趣,只要它们相当常见。
答案1
重定向就可以做到这一点。它的行为与cp
's (如果是目录,-T, --no-target-directory
则错误退出):dst
$ cat src > dst
答案2
就绝对兼容性而言,您可以在尝试复制之前检查目标目录。
要么出错,
[ -d dest ] && echo "${0##*/}: is a directory: dest" >&2 && exit 1
cp src dest
或默默地移除目标
[ -d dest ] && rm -rf dest
cp src dest
没有可用于删除目录并将其替换为文件的原子操作。 (您可能会找到诸如 之类的命令cp --no-target-directory
,但底层操作从根本上来说仍然不是原子的。您所做的只是减少攻击面,而不是消除它。)