web-dev-qa-db-fra.com

Comment copier uniquement les attributs de fichier (métadonnées) sans le contenu réel du fichier?

J'ai déjà copié des téraoctets de fichiers avec rsync mais j'ai oublié d'utiliser --archive pour conserver les attributs spéciaux des fichiers.

J'ai essayé d'exécuter rsync encore cette fois avec --archive mais c'était beaucoup plus lent que ce à quoi je m'attendais. Existe-t-il un moyen simple de procéder plus rapidement en copiant les métadonnées de manière récursive?

20
Mohammad

OK, vous pouvez copier le propriétaire, le groupe, les autorisations et l’horodatage à l’aide du paramètre --reference dans chownname__, chmodname__, touchname__. Voici un script pour le faire

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

Vous devriez l'exécuter avec Sudo(pour autoriser le chown) et avec deux paramètres: le répertoire source et le répertoire de destination. Le script fait uniquement écho à ce qu'il ferait. Si cela vous convient, changez la ligne myecho=echo avec myecho=.

16
enzotib

Traiter la question comme "rsync n'a que des métadonnées à copier, alors pourquoi est-ce si lent, et comment puis-je l'accélérer?":

rsyncutilise généralement des temps égaux comme heuristiques pour détecter et ignorer les fichiers non modifiés. Sans --archive (en particulier, sans --times), les heures du fichier de destination restent définies à l'heure à laquelle vous les avez synchronisées, tandis que les heures du fichier source restent intactes (sans vous tromper manuellement). Sans garantie extérieure de votre part que le contenu des fichiers source n'a pas changé, rsync doit en assumer le risque et doit donc les contrôler et/ou les copier à nouveau dans la destination. Ceci, ajouté au fait que --whole-file est impliqué pour les synchronisations locales-> locales, rend rsyncsans --times approximativement équivalent à cppour les synchronisations locales.

À condition que la mise à jour du contenu des fichiers de destination soit acceptable, ou si les fichiers source ne sont pas modifiés depuis la copie d'origine, vous devriez trouver rsync --archive --size-only plus rapide qu'un rsync naïf.

En cas de doute quant à la copie de rsyncqui prend si longtemps, rsync --archive --dry-run --itemize-changes ... vous indique de manière exhaustive, si concise, les détails.

5
ZakW

AVERTISSEMENT: sans solution de contournement particulière, GNU cp --attributes-only tronquera les fichiers de destination, au moins dans Precise. Voir l'édition ci-dessous.

Original:

Dans cette situation, vous voudrez probablement l'option GNU de --attributes-only de cp, associée à --archive, étant donné qu'il s'agit d'un code éprouvé, tous les attributs agnostiques de systèmes de fichiers ne suivent pas les liens symboliques (les suivre peut être mauvais!):

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

Comme avec les fichiers, cpest additif avec les attributs étendus: si la source et la destination ont des attributs étendus, il ajoute les attributs étendus de la source à la destination (plutôt que de les supprimer). tous les xattrs de la destination en premier). Bien que cela reflète le comportement de cpsi vous copiez des fichiers dans une arborescence existante, il se peut que ce ne soit pas ce que vous attendiez.

Notez également que si vous n'avez pas conservé les liens physiques la première fois avec rsyncmais que vous voulez les conserver maintenant, alors cp--- ne] corrige cela pour vous; vous feriez probablement mieux de relancer rsyncavec les bonnes options (voir mon autre réponse ) et d’être patient.

Si vous avez trouvé cette question en cherchant délibérément ​​séparez et recombinez le contenu des métadonnées/fichiers, jetez un coup d'œil à metastore qui se trouve dans les dépôts Ubuntu.

Source: Manuel GNU coreutils


Édité pour ajouter:

cpfrom GNU coreutilsname__> = 8.17 et supérieur fonctionnera comme décrit, mais coreutils <= 8.16 tronquera les fichiers lors de la restauration de leurs métadonnées. En cas de doute, n'utilisez pas cpdans cette situation; utilisez rsyncwith les bonnes options et/ou soyez patient.

Je ne le recommanderais pas à moins de bien comprendre ce que vous faites, mais il est possible d'empêcher GNU cpde tronquer des fichiers à l'aide de l'astuce 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);
}
5
ZakW

Dans les transferts locaux, lorsque la source et la destination se trouvent sur des systèmes de fichiers montés localement, rsync copiera toujours le contenu de fichiers entiers. Pour éviter cela, vous pouvez utiliser

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

Je devais le faire à distance sur un autre ordinateur afin que je ne puisse pas utiliser - référence

J'ai utilisé cela pour faire le script ...

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

Mais assurez-vous qu'il n'y a pas de noms de fichiers avec "dans eux en premier ...".

find | grep '"'

Copiez ensuite touch.sh sur votre ordinateur distant et lancez ...

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

Il existe également des options dans find -printf pour imprimer l'utilisateur et le nom du groupe si vous souhaitez les copier.

1
niknah