我想创建目录树的“副本”,其中每个文件都是原始文件的硬链接
示例:我有一个目录结构:
dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3
这是预期的结果,目录树的“副本”,其中每个文件都是原始文件的硬链接:
dirB/ # normal directory
dirB/file1 # hardlink to dirA/file1
dirB/x/ # normal directory
dirB/x/file2 # hardlink to dirA/x/file2
dirB/y/ # normal directory
dirB/y/file3 # hardlink to dirA/y/file3
答案1
在 Linux(更准确地说,使用 GNU 和通常在以 Linux 作为内核的系统上找到的busybox
实现cp
)和最近的 FreeBSD 上,如下所示:
cp -al dirA dirB
对于更便携的解决方案,请参阅 Stéphane Chazelas 的使用 pax 和 cpio 的答案
答案2
POSIXly,您可以pax
在读+写模式下使用以下-l
选项:
pax -rwlpe -s /A/B/ dirA .
(-pe
保留复制的文件的所有可能属性(在本例中仅保留目录),就像 GNUcp
所做的那样-a
)。
现在,虽然标准,该命令不一定非常便携的。
首先,许多基于 GNU/Linux 的系统默认不包含pax
(即使这是一个非可选的 POSIX 实用程序)。
然后,一些实现中的许多错误和不符合项会导致该代码出现许多问题。
- 由于错误,Solaris 10
pax
(至少)在-rwl
与-s
.由于某种原因,它似乎将替换应用于原始路径和复制路径。所以上面,它会尝试做一些link("dirB/file", "dirB/file")
而不是link("dirA/file", "dirB/file")
。 - 在 FreeBSD 上,
pax
不会为 类型的文件创建硬链接符号链接(POSIX 允许的行为)。不仅如此,它还将替换应用于符号链接的目标(一种行为不是POSIX 允许)。例如,如果foo -> AA
中有一个符号链接dirA
,它将变成foo -> BA
indirB
。
另外,如果您想对内容存储在$src
和中的任意文件路径执行相同操作$dst
,那么重要的是要认识到创建insidepax -rwl -- "$src" "$dst"
的完整目录结构(必须存在并且是一个目录)。例如,如果is ,则创建。$src
$dst
$src
foo/bar
$dst/foo/bar
相反,如果您想$dst
成为 的副本$src
,最简单的方法可能是这样做:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && pax -rwlpe . "$absolute_dst")
(这也可以解决上面提到的大多数问题,但如果绝对路径$dst
以换行符结尾,则会失败)。
现在这对没有pax
.
有趣的是,它是由 POSIX 创建的,用于合并和命令pax
的功能。tar
cpio
cpio
是一个历史的Unix 命令(从 1977 年开始)与 POSIX 发明相反,并且还有一个 GNU 实现(不是pax
一个)。所以即使它不再是一个标准命令(尽管它是在 SUSv2 中),它仍然很常见,并且有一组您通常可以依赖的核心功能。
相当于。pax -rwl
cpio -pl
然而:
cpio
获取标准输入上的输入文件列表而不是参数(换行符分隔,这意味着不支持带有换行符的文件名)- 必须指定所有文件(通常您向其提供
find
(find
并且cpio
由同一个人联合开发)的输出)。 - 不保留元数据(某些
cpio
实现可以选择保留一些元数据,但没有可移植的)。
所以cpio
:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && find . | cpio -pl "$absolute_dst")
答案3
简短回答:
cd $source_folder
pax -rwlpe . $dest_folder
答案4
如果您正在寻找那个带硬链接的复制制作(全部或部分)文件的快照或备份的功能请查看rsnapshot
。