56

如何在 OS X 中创建指向目录的硬链接(而不是符号链接或 Mac OS 别名)?我已经知道命令“ln target destination”,但仅当目标是文件时才有效。我知道 Mac OS 与其他 Unix 环境不同,它确实允许硬链接到文件夹(例如,这用于 Time Machine),但我自己不知道该怎么做。

4

14 回答 14

53

我同意硬链接文件夹/目录如果不小心可能会导致问题,但它们有一个非常明确的优势 - Time Machine 就是一个完美的例子。没有它们,它根本不实用,因为复制冗余版本的文件会很快消耗掉最大的磁盘。

只要您遵循 Amit Singh 的六个规则,Snow Leopard 就可以创建指向目录的硬链接:

  1. 文件系统必须记录 HFS+。
  2. 源和目标的父目录必须不同。
  3. 源的父级不能是根目录。
  4. 目标不得位于根目录中。
  5. 目标不能是源的后代。
  6. 目标不得有任何作为目录硬链接的祖先。

因此,Snow Leopard 失去了创建文件夹硬链接的能力是完全不正确的。

我刚刚验证了链接/取消链接在 Snow Leopard 上确实有效 - 只要您遵循六条规则。我刚刚试了一下,它在我的 Snow Leopard 10.6.6 系统上运行良好 - 在启动卷和单独的 USB 外部卷上试了一下,在这两种情况下都运行良好。

这是“hunlink.c”程序:

#include <stdio.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
   if (argc != 2)
      return 1;
   int ret = unlink(argv[1]);
   if (ret != 0)
      perror("unlink");
   return ret;
}

gcc -o hunlink hunlink.c

所以,如果你尝试它要小心——记住要遵守规则并使用 hlink 创建这些硬链接,然后使用 hunlink 删除硬链接。并且不要忘记记录您为以后或可能需要知道这一点的其他人所做的事情。

我刚刚了解到这些文件夹的“硬链接”的另一个“陷阱”。当您创建它们时,Mac OS X 的“幕后”确实发生了很多事情。一个非常重要的问题是,您创建链接的文件夹实际上被移动到了一个名为 /.HFS+ 的超级神奇的超级隐藏文件夹Private Directory Data%000d/dir_xxx 其中 xxx 是“source_folder”的 inode 编号 - 请记住命令的格式是

hlink source_folder target_folder

因此,因此,您必须小心不要在“source_folder”中打开任何文件,因为如果这样做,它们就会被移动到超级神奇的文件夹中,如果您尝试保存任何更改,您可能会遇到问题到那些在“source_folder”中打开的文件。这发生在我身上几次,直到我明白发生了什么并且解决方案非常简单。我注意到您不能再执行“ls -la”命令而不会为原始“source_folder”中的所有文件夹/目录出现有趣的错误,但您可以执行“ls”命令并且一切看起来都很好。

如果您在“磁盘工具”程序中运行“验证磁盘”,您会注意到它可能会抱怨并给出“卷位图需要对孤立块进行小修”,这就是创建超级神奇文件夹时发生的情况“source_folder”向其移动。

如果您确实发现自己处于这种“孤立块”的情况,首先将更改的文件保存到不在包含“source_folder”树的卷中的其他临时位置,然后使用“磁盘工具”卸载并重新安装包含“source_folder”或只是重新启动计算机。然后将您保存到临时位置的文件复制回其原始位置,您应该可以恢复业务。这对我有用,所以不能保证这对你也有用。因此,在您有良好备份的卷上尝试此操作可能是一个好主意,以防万一。

看起来很奇怪,所有这些开销都发生在创建文件夹硬链接的简单任务上。有谁知道为什么 Mac OS X 会为创建到文件夹的硬链接而付出所有这些努力?这与这是一个“日志式”文件系统这一事实有关吗?

通过阅读 Amit Singh 对他的“hfsdebug”实用程序的解释,我发现了有关超级神奇、超级隐藏位置的信息。如果您想了解更多详细信息,请访问他的网站Amit Singh 的 hfsdebug 实用程序。这是一个非常有趣的软件,它会告诉你很多关于 HFS+ 文件系统的细节。它是免费的,我鼓励您下载并试用。它不再受支持,但它仍然适用于 Snow Leopard 和 Leopard - 基本上是任何支持 HFS+ 的系统。你真的不能对它造成任何伤害,因为它是一个“只读”工具——所以它非常适合用来查看文件系统的一些细节。

还有一个关于这些“文件夹硬链接”的问题——一旦你创建了一个超级神奇的超级秘密隐藏文件夹,它就永远存在了。即使您取消了最初创建它的文件夹的链接,这个神奇的文件夹仍然存在。不知道为什么,但确实如此。如果您想尝试一下,可以使用“hfsdebug”来查找。您还可以使用“hfsdebug”来找出驱动器上存在多少这些“到文件夹的硬链接”。有关这些详细信息,请参阅 Amit 关于“hfsdebug”实用程序的文章。

他还有另一个受支持但成本较新的实用程序。它被称为 fileXray,一个人在同一家庭的任意数量的计算机上的个人非商业类型许可证的费用为 79 美元。它有一个详尽的 173 页用户指南,您可以在购买前下载它以查看它可以做什么。不幸的是,没有试用版,因此请阅读手册并查看网站以获取更多详细信息,看看它是否可以帮助您摆脱困境。在他们的网站上了解有关它的所有详细信息 - 请参阅fileXray 网站了解更多信息。

在使用这些指向文件夹的硬链接时,您应该注意几个问题。如果创建它们的卷安装到远程客户端,则可能会出现严重问题,具体取决于它们的安装方式。如果您使用 AFP 将卷挂载到远程客户端,则存在很大的问题,因为当前有硬链接或曾经有硬链接但后来被删除的任何文件夹将无法用作所有较低级别的文件夹(但不是文件)将无法从 Finder 或终端窗口访问。如果您尝试执行简单的“ls -lR”命令,它将失败并为您提供所有较低级别文件夹的“ls: xxx: No such file or directory”错误消息。如果您使用 Finder 窗口遍历远程卷的目录树,

如果您使用 NFS 挂载远程客户端(并假设您在系统上有一个 NFS 服务器将该卷作为本地 HFS+ 文件系统),则这些问题似乎不会发生(除了错误消息)。此处未提供有关如何使用 NFS 挂载卷的详细信息。我使用了 Marcel Bresink 博士提供的一个名为“NFS Manager”的好程序来帮助在服务器和客户端上安装 NFS。你可以从他的网站上得到它——只需在你最喜欢的搜索引擎中搜索“Bresink NFS Manager”,但他有一个免费试用版,所以你可以在购买前试用。如果您想学习如何进行 NFS 挂载,这没什么大不了的,但是“NFS 管理器”使设置和调整所有不同的设置以帮助优化它变得非常容易。他还有其他几款价格非常合理的简洁 Mac OS X 实用程序 - 一款称为“硬件监视器”,可让您监控和绘制各种数据,如电源使用情况、CPU 温度、风扇速度以及两者的许多其他变量长时间(从几分钟到几天)的本地和远程 Mac 系统。如果您喜欢方便的实用程序,绝对值得一试。

我确实注意到的一件事是,NFS 文件传输比通过 AFP 传输要慢 20%,但是您的“里程可能会有所不同”,所以不能保证一种或另一种方式,但我宁愿有一些可以工作的东西,即使我有与根本没有任何工作相比,要付出 20% 的性能损失。

Apple 意识到硬链接和远程 AFP 文件系统的问题,他们将其称为 AFP 客户端的“实施限制”——我更愿意称它为在我看来的真实情况——一个错误!!!我只能希望 Mac OS X 的下一个版本能解决这个问题,因为我真的很喜欢能够在有意义的时候使用硬链接到文件夹。

这些笔记是我个人的意见,我不保证它们的正确性,所以使用它们需要您自担风险。在使用这些“文件夹的硬链接”之前,请做好备份,以防万一发生意外情况。但是,如果您决定更多地了解 Mac OS X 的这个有趣方面,我希望您会玩得开心。

于 2011-01-16T18:32:44.023 回答
31

那你不能直接在 BASH 中做。但是...我在这里找到了一篇文章,讨论了如何间接地做到这一点:http: //www.mactech.com/articles/mactech/Vol.23/23.11/ExploringLeopardwithDTrace/index.html通过编译一个简单的小 C 程序:

#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
   if (argc != 3) return 1;

   int ret = link(argv[1], argv[2]);

   if (ret != 0) perror("link");

   return ret;
}

...并在 Terminal.app 中构建:

$ gcc -o hlink hlink.c -Wall
于 2009-04-30T01:20:24.220 回答
16

废话。在 10.5 上,它在ln的手册页中告诉您:

   -d, -F, --directory
          allow the superuser to attempt to hard link  directories  (note:
          will  probably  fail  due  to  system restrictions, even for the
          superuser)

所以是的:

    sudo  ln  -d  existing_dir  new_hard_link

给它你的密码,你还没有完成。你没有记录它,是吗?您必须记录硬链接目录;即使它是单用户机器。

删除是另一回事:如果您按照通常的方式删除目录,您将删除内容。所以你必须“取消链接”目录:

    unlink  new_hard_link

那里。希望你不要破坏你的文件系统!

于 2010-01-10T18:41:25.173 回答
15

交叉发布这个巧妙地解决问题的好工具,最初由Sam发布:


要安装 Hardlink,请确保您已安装homebrew,然后运行:

brew install hardlink-osx

安装后,创建一个硬链接:

hln [source] [destination]

我还注意到该unlink命令在雪豹上不起作用,所以我添加了一个取消链接的选项:

hln -u destination

有兴趣的人可以在 Github 上找到代码:https ://github.com/selkhateeb/hardlink

于 2016-06-10T07:47:54.130 回答
8

是的,它受到内核和文件系统的支持,但由于它不是为一般用途而设计的,因此它不会暴露给 shell。

您可能可以算出 Time Machine 使用哪些 API 并将它们包装在命令行工具中,但最好听从提示并清楚地引导。

于 2008-09-17T08:35:34.877 回答
7

OSX 版本ln无法做到这一点,但是,正如丰富的另一个答案中所提到的,它的 GNU 版本ln可以在自制软件中作为coreutils公式gln的一部分使用。列出了丰富的答案中提供的带有 OSX 特定警告的选项。换句话说,它并非在所有情况下都有效。究竟是什么决定了它是否有效,似乎并没有在任何地方记录。man gln-d

作为先决条件,安装coreutils

    brew install coreutils

现在你可以这样做:

    sudo gln -d /original_folder /mirror_folder

重要提示:要删除硬链接,您必须使用gunlink

    sudo gunlink /mirror_folder

❗️❗️❗️使用rm或 Finder 也会删除原来的文件夹。

仅供参考:coreutils homebrew 公式提供了通用 unix 工具的 GNU 兼容版本。用于brew list coreutils查看完整列表。

于 2016-10-06T08:57:36.440 回答
4

从 2018 年起不再可能。APFS(在 MacOS High Sierra 10.13 中引入)与目录硬链接不兼容。见https://github.com/selkhateeb/hardlink/issues/31

于 2018-10-11T07:14:08.573 回答
3

我的情况是,我从 Windows 虚拟机中发现,我无法遵循符号链接。(我想在 Internet Explorer 中测试一些 HTML 页面)。我的目录结构有 CSS 和图像文件夹的符号链接。

我解决问题的解决方法是与其他答案暗示的不同方法。我曾经rsync创建文件夹的副本。Rsync 可以解析符号链接并改为复制链接的文件。

这解决了我的问题,而无需使用指向目录的硬链接。如果您只是在处理一小部分文件,这实际上是一个简单的解决方案。

rsync -av --copy-dirlinks --delete ../htmlguide ~/src/
于 2009-10-14T09:00:11.043 回答
1

从链接到的文章中,如果您尝试在与原始目录相同的目录中创建硬链接,您将收到该错误。您必须在其他地方创建它。

于 2010-10-15T02:08:40.553 回答
1

在 Linux 中,您可以使用绑定挂载来模拟硬链接目录。不确定OSX

sudo mount --bind /some/existing_real_contents /else/dummy_but_existing_directory
sudo umount /else/dummy_but_existing_directory
于 2016-04-11T04:46:45.483 回答
1

这也可以使用内置 Perl(来自终端)来完成,而无需编译任何东西。我的具体用例是针对 Google Drive(不支持符号链接),所以下面的例子反映了这个用例。

要将您的“文档”文件夹链接到 Google Drive 以使其同步:

perl -e 'link "/Users/me/Documents", "/Users/me/Google Drive/Documents"'

要从 Google 云端硬盘中删除指向“文档”文件夹的链接:

sudo perl -U -e 'unlink "/Users/me/Google Drive/Documents"'

您需要“root”才能取消链接(请参阅“取消链接”perldoc)。

于 2016-09-13T14:28:02.720 回答
0

另一种解决方案是使用可通过端口安装的 bindfs https://code.google.com/p/bindfs/ :

sudo port install bindfs
sudo bindfs ~/source_dir ~/target_dir
于 2013-02-12T21:44:21.537 回答
-1

简短的回答是你不能。:) (除了可能是 root 用户,更准确地说你不应该这样做。)

Unix 只允许一定数量的目录链接——“..”来自其所有子目录和“.”。从自身内部。其他任何东西都可能导致非常混乱的目录树。这显然是/曾经是 Ken Thompson 的设计决定。

(话虽如此,显然Apple的Time Machine确实这样做了:))

于 2008-09-17T08:06:14.243 回答
-1

如果没有子文件夹,你可以试试

ln 文件夹路径/*. * 目标文件夹

它在 OSX 10.9 上对我有用

于 2013-12-16T00:24:21.143 回答