如何只复制文件属性(元数据)而没有文件的实际内容?

我已经使用rsync复制了数TB的文件,但我忘了使用--archive来保存文件的特殊属性。

我这次尝试使用--archive再次执行rsync ,但它比我预期的要慢。 有没有简单的方法通过递归复制元数据来更快地完成这项工作?

好的,您可以使用--reference参数将所有者,组,权限和时间戳复制到chownchmodtouch 。 这是一个脚本

 #!/bin/bash # Filename: cp-metadata myecho=echo src_path="$1" dst_path="$2" find "$src_path" | while read src_file; do dst_file="$dst_path${src_file#$src_path}" $myecho chmod --reference="$src_file" "$dst_file" $myecho chown --reference="$src_file" "$dst_file" $myecho touch --reference="$src_file" "$dst_file" done 

您应该使用sudo (允许chown)和两个参数运行它:源和目标目录。 该脚本只回显它会做什么。 如果满意,用myecho=改变myecho=echo线。

将问题视为“rsync仅包含要复制的元数据,为什么它如此缓慢,以及如何使其更快?”:

rsync通常使用相等的mtimes作为启发式来检测和跳过未更改的文件。 如果没有--archive (特别是没有时间),目标文件的mtimes仍然设置为你同步它们的时间,而源文件的mtimes保持不变(忽略你的手动技巧)。 如果没有来自您的外部保证,源文件的内容没有改变,rsync必须假定它们可能具有,因此必须校验它们和/或再次将它们复制到目的地。 这个,以及本地 – >本地同步隐含的--whole-file这一事实,使得rsync没有 – 时间大约相当于本地同步的cp

如果更新目标文件的内容是可以接受的,或者如果源文件自原始副本以来不受影响,则应该比天真的rsync更快地找到rsync --archive --size-only

如果对rsync复制的rsync --archive --dry-run --itemize-changes ...长时间的怀疑, rsync --archive --dry-run --itemize-changes ...告诉你详尽无遗的细节。

警告:如果没有特殊的解决方法,GNU cp --attributes-only将截断目标文件,至少在Precise中。 请参阅下面的编辑。

原版的:

在这种情况下,您可能需要GNU cp的--attributes-only选项,以及--archive ,因为它是经过试验和测试的代码,所有与文件系统无关的属性并且不遵循符号链接(跟随它们可能很糟糕!):

 cp --archive --attributes-only /source/of/failed/backup/. /destination/ 

与文件一样, cp与扩展属性相加:如果源和目标都具有扩展属性,则将源的扩展属性添加到目标(而不是首先删除所有目标的xattrs)。 虽然这反映了如果将文件复制到现有树中cp行为,但它可能不是您所期望的。

另请注意,如果您第一次使用rsync时没有保留硬链接但是现在要保留它们,那么cp 将不会为您修复它; 你可能最好用正确的选项重新运行rsync (参见我的其他答案 )并耐心等待。

如果您在寻找故意分离和重新组合元数据/文件内容时发现了这个问题,那么您可能需要查看Ubuntu存储库中的Metastore 。

资料来源: GNU coreutils手册


编辑添加:

来自GNU coreutils > = 8.17及更高版本的cp将按照描述工作,但coreutils <= 8.16将在恢复其元数据时截断文件。 如有疑问,请不要在这种情况下使用cp ; 使用带有正确选项的 rsync和/或耐心等待。

除非你完全理解你在做什么,否则我不会推荐这个,但是可以使用LD_PRELOAD技巧阻止早期的GNU cp截断文件:

 /* * File: no_trunc.c * Author: DJ Capelis with minor changes by Zak Wilcox * * Compile: * gcc -fPIC -c -o no_trunc.o no_trunc.c * gcc -shared -o no_trunc.so no_trunc.o -ldl * * Use: * LD_PRELOAD="./no_trunc.so" cp --archive --attributes-only   */ #define _GNU_SOURCE #include  #define _FCNTL_H #include  extern int errorno; int (*_open)(const char *pathname, int flags, ...); int (*_open64)(const char *pathname, int flags, ...); int open(const char *pathname, int flags, mode_t mode) { _open = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open"); flags &= ~(O_TRUNC); return _open(pathname, flags, mode); } int open64(const char *pathname, int flags, mode_t mode) { _open64 = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64"); flags &= ~(O_TRUNC); return _open64(pathname, flags, mode); } 

在本地传输中,当源和目标位于本地安装的文件系统上时, rsync将始终复制整个文件内容。 为避免这种情况,您可以使用

 rsync -a --no-whole-file source dest 

我不得不远程对另一台计算机执行此操作,因此无法使用–reference

我用它来制作剧本……

find -printf "touch -d \"%Tc\" \"%P\"\n" >/tmp/touch.sh

但请确保没有任何文件名首先包含在其中……

find | grep '"'

然后将touch.sh复制到远程计算机,然后运行…

cd ; sh /tmp/touch.sh

如果要复制那些,还可以在find -printf中选项来打印用户,组名。