Как скопировать только атрибуты файла (метаданные) без фактического содержимого файла?
Я уже скопировал терабайты файлов с rsync
но я забыл использовать --archive
сохранить специальные атрибуты файлов.
Я пытался выполнить rsync
снова на этот раз с --archive
но это было намного медленнее, чем я ожидал. Есть ли простой способ сделать это быстрее, просто рекурсивно копируя метаданные?
5 ответов
Хорошо, вы можете скопировать владельца, группу, разрешение и метки времени, используя --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=
,
Отвечая на вопрос как "rsync только копирует метаданные, так почему же он такой медленный и как я могу сделать это быстрее?":
rsync
обычно использует одинаковые значения mtimes в качестве эвристики для обнаружения и пропуска неизмененных файлов. Без --archive
(в частности, без --times
mtimes конечных файлов остаются установленными на время их повторной синхронизации, в то время как mtimes исходных файлов остаются нетронутыми (не обращая внимания на ручной обман). Без внешних гарантий от вас, что содержимое исходных файлов не изменилось, rsync должен предположить, что они могут иметься, и поэтому должен проверять их и / или снова копировать в место назначения. Это плюс тот факт, что --whole-file
подразумевается для локальной-> локальной синхронизации, делает rsync
без --times
примерно эквивалентно cp
для локальной синхронизации.
При условии, что обновление содержимого целевых файлов является приемлемым, или если исходные файлы не затронуты со времени оригинальной копии, вы должны найти rsync --archive --size-only
быстрее, чем наивный rsync.
Если вы сомневаетесь в том, что rsync
копирование, которое занимает так много времени, rsync --archive --dry-run --itemize-changes ...
говорит вам в исчерпывающей, если кратко, подробно.
WARNING: Without special workarounds, GNU cp --attributes-only
will truncate the destination files, at least in Precise. See the edit below.
Оригинал:
In this situation you probably want GNU cp's --attributes-only
option, together with --archive
, as it's tried and tested code, does all filesystem-agnostic attributes and doesn't follow symlinks (following them can be bad!):
cp --archive --attributes-only /source/of/failed/backup/. /destination/
As with files, cp
является аддитивным с расширенными атрибутами: если и источник, и пункт назначения имеют расширенные атрибуты, он добавляет расширенные атрибуты источника к месту назначения (вместо того, чтобы сначала удалить все xattrs назначения). Хотя это отражает, как cp
ведет себя, если вы копируете файлы в существующее дерево, это может не соответствовать вашим ожиданиям.
Также обратите внимание, что если вы не сохранили жесткие ссылки в первый раз с rsync
но хочу сохранить их сейчас cp
не исправлю это для вас; ты, наверное, лучше перезапускать rsync
с правильными вариантами (см. мой другой ответ) и терпением.
Если вы нашли этот вопрос, пытаясь преднамеренно разделить и рекомбинировать содержимое метаданных / файлов, вы можете взглянуть на metastore, который находится в репозиториях 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);
}
Мне пришлось сделать это удаленно на другой компьютер, чтобы я не мог использовать --reference
Я использовал это, чтобы сделать сценарий...
find -printf "touch -d \"%Tc\" \"%P\"\n" >/tmp/touch.sh
Но сначала убедитесь, что в них нет имен файлов с "...
find | grep '"'
Затем скопируйте файл touch.sh на удаленный компьютер и запустите...
cd <DestinationFolder>; sh /tmp/touch.sh
В find -printf также есть опции для печати пользователя, имени группы, если вы хотите скопировать их.
В локальных передачах, когда источник и назначение находятся в локально смонтированных файловых системах, rsync
всегда будет копировать весь контент файлов. Чтобы избежать этого вы можете использовать
rsync -a --no-whole-file source dest