Gud*_*Orn 77 hard-link cp recursive files
我想创建一个目录树的“副本”,其中每个文件都是原始文件的硬链接
示例:我有一个目录结构:
dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3
Run Code Online (Sandbox Code Playgroud)
这是预期的结果,目录树的“副本”,其中每个文件都是原始文件的硬链接:
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
Run Code Online (Sandbox Code Playgroud)
Gud*_*Orn 76
在 Linux(更准确地说是 GNU 和busybox在cp以 Linux 作为内核的系统上常见的实现)和最近的 FreeBSD 上,这是如何:
cp -al dirA dirB
Run Code Online (Sandbox Code Playgroud)
有关更便携的解决方案,请参阅 Stéphane Chazelas 使用 pax 和 cpio 的答案
Sté*_*las 29
POSIXly,您可以pax在读+写模式下使用以下-l选项:
pax -rwlpe -s /A/B/ dirA .
Run Code Online (Sandbox Code Playgroud)
(-pe保留被复制文件的所有可能的属性(在这种情况下,只有目录),如GNUcp的-a一样)。
现在,虽然是标准的,但该命令不一定非常便携。
首先,许多基于 GNU/Linux 的系统pax默认不包含(即使这是一个非可选的 POSIX 实用程序)。
然后,一些实现的许多错误和不一致性导致该代码出现许多问题。
pax(至少)-rwl在与-s. 出于某种原因,它似乎将替换应用于原始路径和复制路径。所以在上面,它会尝试做一些link("dirB/file", "dirB/file")而不是link("dirA/file", "dirB/file").pax不会为符号链接类型的文件创建硬链接(POSIX 允许的行为)。不仅如此,但它也适用于替代的符号链接的目标(行为不通过POSIX允许的)。因此,举例来说,如果有一个foo -> AA符号链接dirA,它将成为foo -> BA在dirB。此外,如果您想使用其内容存储在$srcand 中的任意文件路径执行相同操作$dst,那么重要的是要意识到pax -rwl -- "$src" "$dst"创建$srcinside的完整目录结构$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")
Run Code Online (Sandbox Code Playgroud)
(这也可以解决上面提到的大多数问题,但如果$dst以换行符结尾的绝对路径会失败)。
现在这对没有pax.
有趣的是,它pax是由 POSIX 创建的,用于合并tar和cpio命令的功能。
cpio是一个历史悠久的Unix 命令(从 1977 年开始),而不是 POSIX 发明,并且还有一个 GNU 实现(不是pax一个)。因此,即使它不再是标准命令(尽管它在 SUSv2 中),但它仍然很常见,并且有一组您通常可以依赖的核心功能。
相当于pax -rwl将是cpio -pl。然而:
cpio 使用 stdin 上的输入文件列表而不是参数(换行符分隔,这意味着不支持带有换行符的文件名)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")
Run Code Online (Sandbox Code Playgroud)
rsync -av --link-dest="$PWD/dirA" dirA/ dirB
如果您碰巧已经rsync安装了这个命令,那么这是一个快速简单的命令。为了处理符号链接,您可能需要选择--links, --copy-links, --copy-unsafe-links或--safe-links
从 rsync 手册页:
--link-dest=DIR hardlink to files in DIR when unchanged
-l, --links copy symlinks as symlinks
-L, --copy-links transform symlink into referent file/dir
--copy-unsafe-links only "unsafe" symlinks are transformed
--safe-links ignore symlinks that point outside the tree
Run Code Online (Sandbox Code Playgroud)
编辑:
$ cd /tmp && rm -rf a b; mkdir a && touch a/c && echo "xxx" > a/c && rsync -av --link-dest="$PWD/a" a/ b;
$ ls -lR a b
building file list ... done
created directory b
./
sent 74 bytes received 26 bytes 200.00 bytes/sec
total size is 4 speedup is 0.04
a:
total 8
-rw-r--r-- 2 user wheel 4 Aug 26 16:09 c
b:
total 8
-rw-r--r-- 2 user wheel 4 Aug 26 16:09 c
Run Code Online (Sandbox Code Playgroud)