如何僅複製文件屬性(元資料)而不複製文件的實際內容?

如何僅複製文件屬性(元資料)而不複製文件的實際內容?

我已經複製了數 TB 的文件,rsync但我忘記使用它--archive來保留文件的特殊屬性。

rsync這次我再次嘗試執行--archive,但速度比我預期的要慢得多。有沒有簡單的方法可以透過遞歸複製元資料來更快地完成此操作?

答案1

好的,您可以使用參數將擁有者、群組、權限和時間戳複製--referencechown, 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

您應該使用sudo(以允許 chown)和兩個參數來運行它:來源目錄和目標目錄。該腳本僅回顯它將執行的操作。如果滿意,請更改myecho=echo線路myecho=

答案2

將問題視為「rsync 只需要複製元數據,那麼為什麼它這麼慢,以及如何使其更快?」:

rsync通常使用相等的 mtime 作為啟發式來偵測並跳過未變更的檔案。如果沒有--archive(特別是沒有--times),目標檔案的 mtime 仍設定為您對它們進行 rsync 的時間,而原始檔案的 mtime 則保持不變(忽略您的手動欺騙)。如果沒有來自您的外部保證來源檔案的內容沒有更改,rsync 必須假設它們可能已經更改,因此必須對它們進行校驗和和/或再次將它們複製到目標。這一點,再加--whole-file上本地->本地同步隱含的事實,使得rsync沒有--times大致相當於cp本地同步。

如果更新目標檔案的內容是可以接受的,或者如果原始檔案自原始副本以來沒有受到任何影響,您應該會發現rsync --archive --size-only比簡單的 rsync 更快。

如果您對rsync複製的內容有疑問,需要花費這麼長時間,rsync --archive --dry-run --itemize-changes ...我們會以詳盡而簡潔的方式告訴您。

答案3

警告:如果沒有特殊的解決方法,GNUcp --attributes-only將截斷目標文件,至少在 Precise 中是如此。請參閱下面的編輯。

原來的:

在這種情況下,您可能需要 GNU cp 的--attributes-only選項以及 ,--archive因為它是經過嘗試和測試的程式碼,執行所有與檔案系統無關的屬性並且不遵循符號連結(遵循它們可能會很糟糕!):

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

與檔案一樣,cp它與擴充屬性相加:如果來源和目標都具有擴充屬性,則它添加來源的擴充屬性到目標(而不是先刪除目標的所有 xattrs)。雖然這反映了cp將文件複製到現有樹中時的行為方式,但它可能不是您所期望的。

另請注意,如果您第一次沒有保留硬鏈接,rsync但現在想保留它們,那麼cp 慣於為你解決這個問題;您可能最好rsync使用正確的選項重新運行(請參閱我的其他答案)並保持耐心。

如果您在尋找時發現這個問題故意地分離並重新組合元資料/文件內容,那麼您可能想看看元儲存它位於 Ubuntu 儲存庫中。

來源:GNU coreutils 手冊


編輯新增:

cpGNU 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);
}

答案4

在本機傳輸中,當來源和目標位於本機安裝的檔案系統上時,rsync將始終複製整個檔案內容。為了避免這種情況,你可以使用

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

相關內容