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


21

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

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


「メタデータ」とは、ファイルのパーミッションと所有権、または拡張ファイル属性のようなより複雑なものを意味しますか?
マルセルスティムバーグ

ソースファイルが存在するファイルシステムはローカルにマウントされていますか?
-enzotib

メタデータとは、許可とタイムスタンプを意味します。タイムスタンプは私にとって特に重要です。
モハマド

ソースと宛先の両方のファイルシステムがローカルにマウントされます。
モハンマド

回答:


17

[OK]を、あなたが使用して、所有者、グループ、権限およびタイムスタンプをコピーすることができます--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=echoをで変更しmyecho=ます。


1
はい、それは私が必要とするものです:chmodの参照。ありがとうございました。そして、誰かがタイムスタンプをコピーするためのchmod --referenceのようなものを紹介できたら本当に感謝しています。
モハマド

1
@Mohammad:そのために使用できますtouch --reference=otherfile file。回答を更新しました
enzotib

それは素晴らしいことです。実際、私はちょうど今タッチマニュアルを読んでいた;-)
モハマド

注:touch設計上、変更時間とアクセス時間のみを変更するため、「作成」時間は影響を受けません。(とにかくext2 / 3はctimeの変更をサポートしていないと思いますが、NTFSなどを使用している場合は問題になるかもしれません)。
アムロ

既存のファイルのメタデータのみを変更し、ファイルの存在を保証する必要がない場合-cは、touchコマンドにスイッチを追加して、で空のファイルの作成を停止します$dst_path
シンクロ

5

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

元の:

この状況では、おそらく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しておよび/または我慢してください。

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

errornoであるべきerrnoですよね?
-enzotib

それを削除する簡単なテストはうまくいくようですので、私はオリジナルの冗長性/ミスを永続させたと思いますが、とにかく誰もが新しいcoreutilsを使用することになります。
ZakW

しかし、あなたrsyncが正しいオプションで呼び出すのは、別の質問への答えです...
ジャンポール

5

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

rsync通常、未変更のファイルを検出してスキップするためのヒューリスティックとして等しいmtimesを使用します。なし--archive(具体的には、なし--timesmtimeの(あなたによって手動策略を無視して)そのまま残る)先のファイルはソースファイル間、mtimeのは、あなたがそれらをrsyncの-ED時に設定されたままは。ソースファイルの内容が変更されていないことを外部から保証しない場合、rsyncはファイルが存在する可能性があると想定するため、チェックサムおよび/またはコピー先に再度コピーする必要があります。これに加え、実際に--whole-fileローカルから>ローカル同期のために暗示されるが、作るrsyncなし--timesとほぼ同等cpのローカル同期のために。

宛先ファイルのコンテンツの更新が許容される場合、またはソースファイルが元のコピーから変更されていない場合はrsync --archive --size-only、単純なrsyncよりも迅速に検索する必要があります。

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


1
非常に役立つ情報。--archive --size-onlyは素晴らしいコンボです。宛先にすでに存在するファイルの再コピーを防ぐだけでなく、メタデータも更新します。rsyncのmanページには--size-onlyがサイズが一致する「スキップ」ファイルとして記述されているため、これは私にとっては予想外でした。コピーをスキップするだけですが、メタデータは同期されます。理想的です。
チャドフォンナウ

2

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

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

--no-whole-fileと--progressを使用してrsyncを試しましたが、コピーの進行状況を確認できます(約30 MB /秒)。まだ十分に高速ではないようです。rsyncに対する希望を失いつつあります...-
モハンマド

このオプションはrsync、ファイルが両方ともローカルパスにある場合にショートカットを使用しないように指示するために使用されますがrsync、コンテンツのコピーを妨げません。
ジャンポール

1

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

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

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

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

find | grep '"'

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

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

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


a) "シェルスクリプトを使用する"およびb)を使用して上記のスクリプトを生成するためのアイデアに感謝しfindます。私は同じ状況にありました-属性をコピーするのを忘れて、ソースと宛先ディスクはすでに別のマシンにあり、本当にそれを元に戻したくありませんでした。
i336_
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.