cp 命令遵循目标处的符号链接并破坏链接目标,而不是覆盖链接

cp 命令遵循目标处的符号链接并破坏链接目标,而不是覆盖链接

我有一个符号链接sd/common.py -> actual_file,我想用生成的文件替换该链接。

然而,每当我这样做时

cp /tmp/Star_Wrangler/common.py sd/common.py

...它复制/tmp/Star_Wrangler/common.py并覆盖,actual_file而不是像我想要的那样仅仅替换符号链接。每次我忘记在复制之前删除符号链接时,这种情况都会发生。

是否可以选择获得我期望的行为?我查看了手册,但他们都谈论源的符号链接,而不是目标的符号链接。

答案1

这取决于您使用的 Unix。

在某些 BSD 系统(OpenBSD、FreeBSD)上,您会发现它将cp -f取消链接(删除)符号链接并将其替换为源代码。

使用 GNU cp,这不会产生相同的效果,并且您需要使用 long 选项--remove-destination

在 macOS 上,cp -c如手册所述,使用“复制文件clonefile(2)”。

在 NetBSD 上,使用cp -a(“归档模式”,与该系统上的相同cp -RpP)。这在 GNU、macOS、OpenBSD 或 FreeBSD 上不起作用,即使所有这些系统都有相同或相似的-a选项cp(在 GNU 系统上,它与 相同-dR --preserve)。

您自己已经提到过这一点:在复制文件之前删除链接将解决该问题。该rm实用程序删除链接而不是链接引用的文件。这也是用常规文件替换符号链接的最便携的方法。

如果您正在编写脚本,那么我建议您使用rm后跟cp.

如果您正在交互工作并且总是忘记执行此操作,那么您也可能忘记cp针对这些情况使用特定选项。

答案2

符号链接的行为非常令人困惑,不仅是cp,还包括chmodchown内置函数test(或其[ .. ]别名)。

首先删除符号链接rm -f sd/common.py), 然后cp

当然,不同系统上的不同cp版本有不同的选项来执行此操作,但很容易措手不及。

您可以做的另一件事是避免cp并瞄准符号链接结果。ln -sf SOURCE DESTINATION(两个参数都是绝对路径)适用于所有 POSIX 系统,不会造成任何进一步的混乱。-f删除任何现有的DESTINATION文件/符号链接(但不是目录,唉)。您可以将其与realpath避免相对/绝对路径问题结合起来:

ln -sf "$(realpath "$SOURCE")" "$(realpath "$DESTINATION")"

相关内容