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

Moh*_*mad 23 filesystem rsync metadata

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

rsync这次我尝试再次执行,--archive但它比我预期的要慢。有没有什么简单的方法可以通过递归复制元数据来更快地做到这一点?

enz*_*tib 21

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

#!/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
Run Code Online (Sandbox Code Playgroud)

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


小智 7

将问题视为“rsync 只有要复制的元数据,为什么它这么慢,我怎样才能让它更快?”:

rsync通常使用相等的 mtimes 作为启发式来检测和跳过未更改的文件。没有--archive(特别是没有--times)目标文件的 mtime 保持设置为您同步它们的时间,而源文件的 mtime 保持不变(忽略您的手动技巧)。如果您没有外部保证源文件的内容没有更改,rsync 必须假设它们可能已经更改,因此必须对它们进行校验和/或再次将它们复制到目的地。这,再加上实际上--whole-file是隐含的局地>本地同步,使得rsync无需--times大约相当于cp本地同步。

如果更新目标文件的内容是可以接受的,或者如果源文件自原始副本以来未受影响,您应该会发现rsync --archive --size-only比天真的 rsync 更快。

如果对rsync复制需要这么长时间的内容有疑问,rsync --archive --dry-run --itemize-changes ...请详尽详尽地告诉您。

  • 非常有用的信息。--archive --size-only 是一个很好的组合。它不仅可以防止重新复制目标中已经存在的文件,而且还会更新它们的元数据。这对我来说是出乎意料的,因为 rsync 的手册页将 --size-only 描述为“跳过”大小匹配的文件。事实证明它只是跳过了副本,但仍会同步元数据。理想的。 (3认同)

小智 5

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

原来的:

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

cp --archive --attributes-only /source/of/failed/backup/. /destination/
Run Code Online (Sandbox Code Playgroud)

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

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

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

来源:GNU coreutils 手册


编辑添加:

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

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

/*
 * File: no_trunc.c
 * Author: D.J. 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 <src...> <dest>
 */

#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <bits/fcntl.h>

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);
}
Run Code Online (Sandbox Code Playgroud)