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

21

Já copiei terabytes de arquivos, rsyncmas esqueci de usá-lo --archivepara preservar os atributos especiais dos arquivos.

rsyncDesta vez, tentei executar novamente, --archivemas era muito mais lento do que eu esperava. Existe alguma maneira fácil de fazer isso mais rápido, copiando metadados recursivamente?

Mohammad
fonte
Com "metadados", você quer dizer permissões e propriedade de arquivos ou coisas mais complicadas, como atributos de arquivo estendidos?
Marcel Stimberg
O sistema de arquivos em que os arquivos de origem residem é montado localmente ou não?
enzotib 12/08
por metadados, quero dizer permissões e carimbos de hora. os carimbos de hora são particularmente importantes para mim.
Mohammad
o sistema de arquivos na origem e no destino é montado localmente.
Mohammad

Respostas:

17

Ok, você pode copiar proprietário, grupo, permissão e marcas de tempo usando o --referenceparâmetro 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 script apenas faz eco do que faria. Se satisfeito, altere a linha myecho=echocom myecho=.

enzotib
fonte
1
Sim, é disso que eu preciso: - referência no chmod. Obrigado. E eu realmente aprecio se alguém possa introduzir algo como chmod --reference para copiar carimbos de data / hora.
Mohammad
1
@ Mohammad: para isso você pode usar touch --reference=otherfile file. Atualizada a resposta
enzotib
Isso é ótimo. Na verdade, eu estava lendo o manual toque só agora ;-)
Mohammad
Apenas uma observação: touchpor design, apenas altera os tempos de modificação e acesso, o tempo de "criação" não é afetado. (Eu acho que o ext2 / 3 não suporta a alteração do ctime, mas pode ser importante se você estiver usando NTFS ou algo semelhante).
Amro
Caso você queira alterar apenas os metadados dos arquivos existentes e não precisar garantir a existência dos arquivos, adicione uma -copção ao touchcomando para impedir a criação de arquivos vazios no arquivo $dst_path.
Synchro
5

AVISO: Sem soluções especiais, o GNU cp --attributes-onlytruncará os arquivos de destino, pelo menos no Precise. Veja a edição abaixo.

Original:

Nesta situação, você provavelmente deseja a --attributes-onlyopção do GNU cp , juntamente com --archive, como é um código testado e testado, faz todos os atributos independentes 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/

Como nos arquivos, cpé aditivo com atributos estendidos: se a origem e o destino tiverem atributos estendidos, os atributos estendidos da fonte serão adicionados ao destino (em vez de excluir primeiro todos os xattrs do destino). Embora isso reflita como cpse comporta se você copiar arquivos para 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, rsyncmas deseja preservá-los agora, cp não o corrigirá; provavelmente é melhor executar novamente rsynccom as opções corretas (veja minha outra resposta ) e ser paciente.

Se você encontrou essa pergunta enquanto procurava deliberadamente separar e recombinar o conteúdo de metadados / arquivos, pode dar uma olhada no metastore que está nos repositórios do Ubuntu.

Fonte: Manual do GNU coreutils


Editado para adicionar:

cpdo GNU coreutils> = 8.17 e superior funcionará como descrito, mas o coreutils <= 8.16 truncará arquivos ao restaurar seus metadados. Em caso de dúvida, não use cpnesta situação; use rsynccom 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 anterior cppode 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);
}
ZakW
fonte
errornodeveria ser errno, certo?
enzotib
Um rápido teste para removê-lo parece funcionar, então eu acho que perpetuou uma redundância / erro no original , mas todo mundo já estará usando os coreutils mais novos agora.
ZakW 15/04
mas o que você chama rsynccom as opções certas é uma resposta para outra pergunta ...
Jean Paul
5

Tratar a pergunta como "o rsync possui apenas metadados para copiar; por que é tão lento e como posso torná-lo mais rápido?":

rsyncgeralmente usa mtimes iguais como heurística para detectar e pular arquivos inalterados. Sem --archive(especificamente, sem --times), os tempos dos arquivos de destino permanecem definidos para o tempo em que você os sincroniza, enquanto os tempos dos arquivos de origem permanecem intactos (ignorando os truques manuais por você). Sem garantias externas suas de que o conteúdo dos arquivos de origem não foi alterado, o rsync deve assumir que eles podem ter e, portanto, deve soma-los e / ou copiá-los para o destino novamente. Isso, mais o fato --whole-fileimplícito nas sincronizações local-> local, torna rsyncsem --timesaproximadamente equivalente ao cpdas sincronizações locais.

Desde que a atualização do conteúdo dos arquivos de destino seja aceitável ou se os arquivos de origem estiverem intocados desde a cópia original, você deve encontrar rsync --archive --size-onlymais rapidamente do que um rsync ingênuo.

Em caso de dúvida quanto ao processo de rsynccópia que está demorando tanto, rsync --archive --dry-run --itemize-changes ...informa com detalhes exaustivos, embora concisos.

ZakW
fonte
1
Informação muito útil. --archive --size-only é uma ótima combinação. Isso não apenas impede a cópia de arquivos que já existem no destino, mas também atualiza seus metadados. Isso foi inesperado para mim, porque a página de manual do rsync descreve --size-only como "pulando" arquivos cujos tamanhos correspondem. Acontece que apenas pula a cópia, mas ainda sincroniza os metadados. Ideal.
Chad von Nau
2

Nas transferências locais, quando a origem e o destino estão em sistemas de arquivos montados localmente, rsyncsempre copia todo o conteúdo dos arquivos. Para evitar isso, você pode usar

rsync -a --no-whole-file source dest
enzotib
fonte
Tentei o rsync com --no-file-inteiro e --progress e ainda consigo ver o progresso da cópia (cerca de 30 MB / s); então acho que ainda não é rápido o suficiente. Estou perdendo a minha esperança no rsync ...
Mohammad
Esta opção é usada para dizer para rsyncnão usar o atalho quando os arquivos estiverem no caminho local, mas não impede a rsynccópia do conteúdo.
Jean Paul
1

Eu tive que fazer isso remotamente em outro computador para não poder usar - referência

Eu usei isso para fazer o script ...

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

Mas verifique se não há nomes de arquivos com "neles primeiro ...

find | grep '"'

Copie o touch.sh para o seu computador remoto e execute ...

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

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

niknah
fonte
Obrigado pelas idéias de a) "basta usar um script de shell" eb) para gerar o referido script usando find. Eu estava na mesma situação - esqueci de copiar atributos, os discos de origem e de destino já estavam em máquinas diferentes e realmente não queriam reverter isso.
I336_