Como copiar apenas atributos de arquivo (metadados) sem conteúdo real do arquivo?

16

Eu já copiei terabytes de arquivos com rsync , mas esqueci de usar --archive para preservar os atributos especiais dos arquivos.

Eu tentei executar rsync novamente dessa vez com --archive , mas foi bem mais lento do que eu esperava. Existe alguma maneira fácil de fazer isso mais rápido apenas copiando os metadados recursivamente?

    
por Mohammad 12.08.2011 / 10:39

5 respostas

14

Ok, você pode copiar proprietário, grupo, permissão e data e hora usando o parâmetro --reference para chown , chmod , touch . Aqui está um script para fazer isso

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

Você deve executá-lo com sudo (para permitir chown) e com dois parâmetros: diretório de origem e destino. O roteiro apenas ecoava o que ele faria. Se satisfeito, altere a linha myecho=echo com myecho= .

    
por enzotib 12.08.2011 / 12:55
5

Tratar a pergunta como "o rsync só tem metadados para copiar, então por que é tão lento e como posso torná-lo mais rápido?":

rsync usualmente usa mtimes iguais como uma heurística para detectar e pular arquivos inalterados. Sem --archive (especificamente, sem --times ) os mtimes dos arquivos de destino permanecem configurados para o tempo que você os rsyncou, enquanto os mtimes dos arquivos de origem permanecem intactos (ignorando os truques manuais feitos por você). Sem garantias externas de você de que o conteúdo dos arquivos de origem não foi alterado, o rsync deve assumir que eles devem ter e, portanto, fazer o checksum deles e / ou copiá-los para o destino novamente. Isso, além do fato de que --whole-file está implícito para sincronizações locais e locais, torna rsync sem --times aproximadamente equivalente a cp para sincronizações locais.

Desde que a atualização do conteúdo dos arquivos de destino seja aceitável, ou se os arquivos de origem não forem tocados desde a cópia original, você deverá encontrar rsync --archive --size-only mais rápido do que um rsync ingênuo.

Em caso de dúvidas sobre o que rsync está copiando que está demorando tanto, rsync --archive --dry-run --itemize-changes ... nos informa em detalhes detalhados e minuciosos.

    
por ZakW 14.06.2012 / 18:41
4

AVISO: Sem alternativas especiais, o GNU cp --attributes-only truncará os arquivos de destino, pelo menos em Precise. Veja a edição abaixo.

Original:

Nesta situação você provavelmente quer a opção --attributes-only do GNU cp, juntamente com --archive , como é código testado e experimentado, faz todos os atributos agnósticos do sistema de arquivos e não segue links simbólicos (segui-los pode ser ruim!):

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

Assim como os arquivos, cp é aditivo com atributos estendidos: se origem e destino tiverem atributos estendidos, adiciona os atributos estendidos da origem ao destino (em vez de excluir todos os xattrs do destino primeiro ). Embora isso espelhe como o cp se comporta se você copiar arquivos em uma árvore existente, pode não ser o que você espera.

Observe também que, se você não preservou os links físicos na primeira vez com rsync , mas deseja preservá-los agora, então cp não o corrigirá para você; você provavelmente é melhor re-executar rsync com as opções corretas (veja minha outra resposta) e ser paciente.

Se você encontrou esta questão enquanto procurava deliberadamente separar e recombinar o conteúdo de metadados / arquivo, talvez queira dar uma olhada em metastore que está nos repositórios do Ubuntu.

Fonte: manual GNU coreutils

Editado para adicionar:

cp do GNU coreutils > = 8.17 e acima funcionarão conforme descrito, mas o coreutils < = 8.16 truncará arquivos ao restaurar seus metadados. Em caso de dúvida, não use cp nesta situação; use rsync com as opções certas e / ou seja paciente.

Eu não recomendaria isso a menos que você entenda completamente o que está fazendo, mas o GNU cp anterior pode ser impedido de truncar arquivos usando o Truque 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);
}
    
por ZakW 28.05.2012 / 03:39
2

Nas transferências locais, quando a origem e o destino estiverem em sistemas de arquivos montados localmente, rsync sempre copiará todo o conteúdo dos arquivos. Para evitar isso, você pode usar

rsync -a --no-whole-file source dest
    
por enzotib 12.08.2011 / 12:25
0

Eu tive que fazer isso remotamente para outro computador, então não pude usar - reference

Eu usei isso para fazer o script ...

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

Mas certifique-se de que não haja nomes de arquivo com "neles primeiro ...

find | grep '"'

Em seguida, copie o touch.sh para o seu computador remoto e execute ...

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

Também existem opções em find -printf para imprimir usuário, nome do grupo se você quiser copiá-las.

    
por niknah 20.10.2014 / 14:32