Как скопировать только атрибуты файла (метаданные) без фактического содержимого файла?

Как скопировать только атрибуты файла (метаданные) без фактического содержимого файла?

Я уже скопировал терабайты файлов с помощью, rsyncно забыл использовать --archiveфункцию сохранения специальных атрибутов файлов.

Я попробовал выполнить rsyncснова на этот раз с помощью , --archiveно это было намного медленнее, чем я ожидал. Есть ли какой-нибудь простой способ сделать это быстрее, просто рекурсивно скопировав метаданные?

решение1

Хорошо, вы можете скопировать владельца, группу, разрешение и временные метки, используя --referenceпараметр в chown, 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обычно использует равные mtimes в качестве эвристики для обнаружения и пропуска неизмененных файлов. Без --archive(в частности, без --times) mtimes файлов назначения остаются установленными на время, когда вы их rsync-или синхронизировали, в то время как mtimes исходных файлов остаются нетронутыми (игнорируя ваши ручные уловки). Без внешних гарантий с вашей стороны, что содержимое исходных файлов не изменилось, rsync должен предположить, что они могли измениться, и поэтому должен проверить их контрольную сумму и/или снова скопировать их в место назначения. Это, а также тот факт, что --whole-fileподразумевается для локальных->локальных синхронизаций, делает rsyncбез --timesприблизительно эквивалентным cpдля локальных синхронизаций.

При условии, что обновление содержимого целевых файлов приемлемо или если исходные файлы не были затронуты с момента создания оригинальной копии, вы должны найти rsync --archive --size-onlyболее быстрый способ, чем простой rsync.

Если у вас есть сомнения относительно того, что rsyncкопирование занимает так много времени, rsync --archive --dry-run --itemize-changes ...расскажет вам исчерпывающую, хотя и лаконичную, информацию.

решение3

ВНИМАНИЕ: Без специальных обходных путей GNU cp --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


Отредактировано для добавления:

cpиз GNU coreutils>= 8.17 и выше будет работать, как описано, но coreutils <= 8.16 будет обрезать файлы при восстановлении их метаданных. Если сомневаетесь, не используйте cpв этой ситуации; используйте rsyncсправильные вариантыи/или будьте терпеливы.

Я бы не рекомендовал этого делать, если вы не понимаете полностью, что делаете, но в более ранних версиях GNU cpможно запретить обрезание файлов с помощьюТрюк 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

Связанный контент