Wie kopiere ich nur Dateiattribute (Metadaten) ohne den eigentlichen Inhalt der Datei?

21

Ich habe bereits Terabytes an Dateien mit kopiert, rsyncaber ich habe vergessen, diese zu verwenden --archive, um die speziellen Attribute von Dateien zu erhalten.

Ich rsynchabe diesmal erneut versucht, mit auszuführen, --archiveaber es war viel langsamer als ich erwartet hatte. Gibt es eine einfache Möglichkeit, dies durch rekursives Kopieren von Metadaten zu beschleunigen?

Mohammad
quelle
Mit "Metadaten" meinen Sie Dateiberechtigungen und Dateibesitz oder kompliziertere Dinge wie erweiterte Dateiattribute?
Marcel Stimberg
Das Dateisystem, in dem sich die Quelldateien befinden, ist lokal gemountet oder nicht?
Enzotib
Mit Metadaten meine ich Berechtigungen und Zeitstempel. Zeitstempel sind für mich besonders wichtig.
Mohammad
Das Dateisystem in Quelle und Ziel ist lokal gemountet.
Mohammad

Antworten:

17

OK, können Sie kopieren Eigentümer, Gruppe, Berechtigung und Zeitstempel mit dem --referenceParameter chown, chmod, touch. Hier ist ein Skript, um dies zu tun

#!/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

Sie sollten es mit sudo(um chown zuzulassen) und mit zwei Parametern ausführen : Quell- und Zielverzeichnis. Das Skript gibt nur wieder, was es tun würde. Wenn Sie zufrieden sind, ändern Sie die Zeile myecho=echomit myecho=.

Enzotib
quelle
1
Ja, das brauche ich: --reference in chmod. Vielen Dank. Und ich schätze es wirklich, wenn jemand so etwas wie chmod - Hinweis zum Kopieren von Zeitstempeln einführen könnte.
Mohammad
1
@Mohammad: dafür kannst du verwenden touch --reference=otherfile file. Die Antwort wurde aktualisiert
enzotib
Das ist großartig. Eigentlich habe ich gerade ein Touch-Handbuch gelesen ;-)
Mohammad
Nur eine Anmerkung: touchDesignbedingt ändert sich nur die Änderungs- und Zugriffszeit, die "Erstellungszeit" wird nicht beeinflusst. (Ich denke, ext2 / 3 unterstützt das Ändern der Uhrzeit sowieso nicht, aber es könnte von Bedeutung sein, wenn Sie NTFS oder ähnliches verwenden).
Amro
Wenn Sie nur die Metadaten vorhandener Dateien ändern möchten und nicht sicherstellen müssen, dass Dateien vorhanden sind, fügen Sie -cdem touchBefehl einen Schalter hinzu, um zu verhindern, dass leere Dateien in der Datei erstellt werden $dst_path.
Synchro
5

WARNUNG: Ohne spezielle Problemumgehungen schneidet GNU cp --attributes-onlydie Zieldateien zumindest in Precise ab. Siehe die Bearbeitung unten.

Original:

In dieser Situation möchten Sie wahrscheinlich, dass die --attributes-onlyOption von GNU cp zusammen mit --archivedem bewährten Code alle dateisystemunabhängigen Attribute ausführt und Symlinks nicht folgt (das Folgen kann schlecht sein!):

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

Wie bei Dateien, cpist additiv mit erweiterten Attributen: Wenn sowohl Quell- und Ziel erweiterte Attribute haben sie fügt die erweiterten Attribute der Quelle zum Ziel ( und nicht zuerst alle das Ziel des xattrs zu löschen). Dies spiegelt zwar das Verhalten cpbeim Kopieren von Dateien in einen vorhandenen Baum wider , entspricht jedoch möglicherweise nicht Ihren Erwartungen.

Beachten Sie auch, dass Sie das Problem nicht beheben können, wenn Sie beim ersten Mal keine festen Verknüpfungen mit rsyncbeibehalten haben, diese aber jetzt beibehalten möchten . Sie sind wahrscheinlich am besten dran, mit den richtigen Optionen (siehe meine andere Antwort ) noch einmal zu laufen und Geduld zu haben.cp rsync

Wenn Sie diese Frage beim absichtlichen Trennen und erneuten Kombinieren von Metadaten / Dateiinhalten gefunden haben, möchten Sie vielleicht einen Blick auf den Metastore werfen, der sich in den Ubuntu-Repositorys befindet.

Quelle: GNU coreutils manual


Bearbeitet, um hinzuzufügen:

cpab GNU coreutils> = 8.17 funktioniert wie beschrieben, aber coreutils <= 8.16 schneidet Dateien beim Wiederherstellen ihrer Metadaten ab. Im Zweifelsfall nicht cpin dieser Situation verwenden; Verwenden Sie rsyncmit den richtigen Optionen und / oder seien Sie geduldig.

Ich würde dies nur empfehlen, wenn Sie genau wissen , was Sie tun, aber cpmit dem LD_PRELOAD-Trick kann verhindert werden, dass frühere GNU- Versionen Dateien abschneiden :

/*
 * 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);
}
ZakW
quelle
errornosollte sein errno, richtig?
Enzotib
Ein schneller Test, der es entfernt, scheint zu funktionieren, also habe ich vermutlich eine Redundanz / einen Fehler im Original aufrechterhalten, aber jetzt werden ohnehin alle auf neueren Coreutils sein.
ZakW
Aber was Sie rsyncmit den richtigen Optionen aufrufen , ist eine Antwort auf eine andere Frage ...
Jean Paul
5

Wenn Sie die Frage so behandeln, dass "rsync nur zu kopierende Metadaten enthält, warum ist sie dann so langsam und wie kann ich sie beschleunigen?":

rsyncVerwendet in der Regel MTIME-Werte als Heuristik, um unveränderte Dateien zu erkennen und zu überspringen. Ohne --archive(insbesondere ohne --times) bleiben die MTIMES der Zieldateien auf den Zeitpunkt eingestellt, zu dem Sie sie erneut synchronisiert haben, während die MTIMES der Quelldateien intakt bleiben (wobei manuelle Tricks von Ihnen ignoriert werden). Ohne externe Garantien von Ihnen, dass sich der Inhalt der Quelldateien nicht geändert hat, muss rsync davon ausgehen, dass dies der Fall ist, und muss sie daher prüfen und / oder erneut in das Ziel kopieren. Dies und die Tatsache , dass --whole-filefür Lokal-> lokale Synchronisierungen impliziert wird, macht rsyncohne --timesentspricht etwa cpfür lokale Synchronisierungen.

Vorausgesetzt, dass die Aktualisierung des Inhalts der Zieldateien akzeptabel ist oder wenn die Quelldateien seit der Originalkopie nicht verändert wurden, sollten Sie rsync --archive --size-onlyschneller als eine naive Synchronisierung fündig werden .

Wenn Sie sich nicht sicher sind, was rsyncdas Kopieren so lange dauert, rsync --archive --dry-run --itemize-changes ...informieren Sie sich ausführlich, wenn auch knapp.

ZakW
quelle
1
Sehr nützliche Infos. --archive --size-only ist eine großartige Kombination. Dies verhindert nicht nur das erneute Kopieren von Dateien, die bereits im Ziel vorhanden sind, sondern aktualisiert auch deren Metadaten. Dies war für mich unerwartet, da die Manpage von rsync --size-only als "Überspringen" von Dateien beschreibt, deren Größe übereinstimmt. Es stellt sich heraus, dass nur die Kopie übersprungen wird, die Metadaten jedoch trotzdem synchronisiert werden. Ideal.
Chad von Nau
2

Bei lokalen Übertragungen werden, wenn sich Quelle und Ziel auf lokal bereitgestellten Dateisystemen befinden, rsyncimmer ganze Dateiinhalte kopiert. Um dies zu vermeiden, können Sie verwenden

rsync -a --no-whole-file source dest
Enzotib
quelle
Ich habe rsync mit --no-whole-file und --progress ausprobiert und sehe immer noch den Kopierfortschritt (ca. 30 MB / s). Ich denke, es ist noch nicht schnell genug. Ich verliere meine Hoffnung auf rsync ...
Mohammad
Mit dieser Option wird festgelegt, dass rsyncdie Verknüpfung nicht verwendet werden soll, wenn sich beide Dateien im lokalen Pfad befinden. Das rsyncKopieren des Inhalts wird jedoch nicht verhindert .
Jean Paul
1

Ich musste dies remote auf einem anderen Computer ausführen, damit ich --reference nicht verwenden konnte

Ich habe das benutzt, um das Skript zu machen ...

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

Aber stellen Sie sicher, dass keine Dateinamen mit "in ihnen zuerst ...

find | grep '"'

Kopieren Sie anschließend touch.sh auf Ihren Remote-Computer und führen Sie Folgendes aus:

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

Es gibt auch Optionen in find -printf zum Drucken von Benutzernamen und Gruppennamen, wenn Sie diese kopieren möchten.

Niknah
quelle
Vielen Dank für die Ideen, a) "nur ein Shell-Skript verwenden" und b) dieses Skript mit zu generieren find. Ich war in der gleichen Situation - habe vergessen, Attribute zu kopieren, Quell- und Zieldatenträger befanden sich bereits auf unterschiedlichen Rechnern und wollten das nicht wirklich rückgängig machen.
i336_