如果 cp 的目标路径是一个目录,如何避免在该目录中错误地创建文件?

如果 cp 的目标路径是一个目录,如何避免在该目录中错误地创建文件?

我的理解cp src dest是:

  1. 如果src是一个文件并且dest不存在,但其父目录存在,则dest创建。
  2. 如果src是一个文件并且dest是一个文件,dest则被 的内容覆盖src
  3. 如果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,但底层操作从根本上来说仍然不是原子的。您所做的只是减少攻击面,而不是消除它。)

相关内容