如何使用每个文件的硬链接递归复制目录

如何使用每个文件的硬链接递归复制目录

我想创建目录树的“副本”,其中每个文件都是原始文件的硬链接

示例:我有一个目录结构:

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 -> BAin dirB

另外,如果您想对内容存储在$src和中的任意文件路径执行相同操作$dst,那么重要的是要认识到创建insidepax -rwl -- "$src" "$dst"的完整目录结构(必须存在并且是一个目录)。例如,如果is ,则创建。$src$dst$srcfoo/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的功能。tarcpio

cpio是一个历史的Unix 命令(从 1977 年开始)与 POSIX 发明相反,并且还有一个 GNU 实现(不是pax一个)。所以即使它不再是一个标准命令(尽管它是在 SUSv2 中),它仍然很常见,并且有一组您通常可以依赖的核心功能。

相当于。pax -rwlcpio -pl然而:

  1. cpio获取标准输入上的输入文件列表而不是参数(换行符分隔,这意味着不支持带有换行符的文件名)
  2. 必须指定所有文件(通常您向其提供findfind并且cpio由同一个人联合开发)的输出)。
  3. 不保留元数据(某些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

相关内容