web-dev-qa-db-ja.com

ファイルの実際のコンテンツなしでファイル属性(メタデータ)のみをコピーする方法は?

既にテラバイトのファイルをrsyncでコピーしましたが、--archiveを使用してファイルの特別な属性を保存するのを忘れていました。

今回は--archiversyncを再度実行しようとしましたが、予想よりもずっと遅くなりました。メタデータを再帰的にコピーするだけで、これを簡単に行う方法はありますか?

20
Mohammad

わかりました。--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を許可するため)および2つのパラメーター:sourceおよびdestinationディレクトリで実行する必要があります。スクリプトは、実行内容をエコーするだけです。満足したら、行myecho=echomyecho=に変更します。

16
enzotib

質問を「rsyncはコピーするメタデータのみを持っているので、なぜそんなに遅いのですか、どうすれば速くできますか?」:

rsyncは、通常、未変更のファイルを検出してスキップするためのヒューリスティックとして等しいmtimesを使用します。 --archiveがない場合(具体的には--timesがない場合)、宛先ファイルのmtimesはrsync-edした時刻に設定されたままで、ソースファイルのmtimesはそのままです(手動によるトリックは無視されます)。ソースファイルのコンテンツが変更されていないことを外部から保証しない場合、rsyncはファイルが存在する可能性があると想定するため、それらをチェックサムしたり、コピー先にコピーしたりする必要があります。これに加えて、ローカル同期で--whole-fileが暗示されるという事実により、--timesなしのrsyncは、ローカル同期のcpとほぼ同等になります。

宛先ファイルのコンテンツの更新が許容される場合、またはソースファイルが元のコピー以降に変更されていない場合は、単純なrsyncよりもrsync --archive --size-onlyをすばやく見つける必要があります。

rsyncのコピーに時間がかかっていることが疑わしい場合、rsync --archive --dry-run --itemize-changes ...は、簡潔な場合でも、詳細を網羅的に示します。

5
ZakW

警告:特別な回避策がなければ、GNU cp --attributes-onlyは少なくとも正確に宛先ファイルを切り捨てます。以下の編集を参照してください。

オリジナル:

この状況では、おそらくGNU cpの--attributes-onlyオプションと--archiveが必要です。コードが試行およびテストされているため、ファイルシステムに依存しない属性をすべて実行し、シンボリックリンクをたどりません(以下を参照)それらは悪い場合があります!):

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

ファイルの場合と同様に、cpは拡張属性を使用して追加できます。ソースと宛先の両方に拡張属性がある場合、addsソースの拡張属性を宛先に追加します(最初に宛先のすべてのxattrsを削除するのではなく)。これは、既存のツリーにファイルをコピーした場合のcpの動作をミラーリングしますが、期待どおりではない場合があります。

また、最初にrsyncでハードリンクを保存しなかったが、今すぐそれらを保存したい場合は、cpはそれを修正しませんあなたのために;おそらく、rsyncを適切なオプション(私の その他の回答 を参照)で再実行し、忍耐強い方がよいでしょう。

意図的に分離してメタデータ/ファイルのコンテンツを再結合しているときにこの質問を見つけた場合は、Ubuntuにある metastore を見てみたいかもしれませんリポジトリ。

ソース: GNU coreutils manual


追加するために編集:

cp from GNU coreutils> = 8.17以降は説明どおりに機能しますが、coreutils <= 8.16はメタデータの復元時にファイルを切り捨てます。疑わしい場合は、この状況でcpを使用しないでください。 rsync正しいオプション とともに使用する、および/または我慢してください。

あなたが何をしているかを完全に理解していない限り、これはお勧めしませんが、以前のGNU cpLD_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);
}
5
ZakW

ローカル転送では、ソースと宛先がローカルにマウントされたファイルシステムにある場合、rsyncは常にファイルの内容全体をコピーします。これを回避するには、次を使用できます

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

これを別のコンピューターにリモートで実行する必要があったため、-referenceを使用できませんでした

これを使ってスクリプトを作成しました...

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

ただし、最初に「」が含まれるファイル名がないことを確認してください...

find | grep '"'

次に、touch.shをリモートコンピューターにコピーして、実行します...

cd <DestinationFolder>; sh /tmp/touch.sh

Find -printfには、ユーザー、グループ名をコピーする場合にそれらを印刷するオプションもあります。

1
niknah