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

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

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

Tentei executar rsyncnovamente desta vez, --archivemas foi bem mais lento do que eu esperava. Existe alguma maneira fácil de fazer isso mais rápido, apenas copiando metadados recursivamente?

Responder1

Ok, você pode copiar proprietário, grupo, permissão e carimbos de data e hora 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 ecoa o que faria. Se estiver satisfeito, altere a linha myecho=echocom myecho=.

Responder2

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

rsyncgeralmente usa mtimes iguais como heurística para detectar e ignorar arquivos inalterados. Sem --archive(especificamente, sem --times) os mtimes dos arquivos de destino permanecem definidos para o horário em que você os sincronizou novamente, enquanto os mtimes dos arquivos de origem permanecem intactos (ignorando seus truques manuais). 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 mudado e, portanto, deve verificá-los e/ou copiá-los para o destino novamente. Isso, mais o fato de --whole-fileestar implícito nas sincronizações locais-> locais, torna- rsynco --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 não foram alterados desde a cópia original, você deve achar rsync --archive --size-onlymais rápido do que um rsync ingênuo.

Em caso de dúvida sobre o que rsyncestá demorando tanto para copiar, rsync --archive --dry-run --itemize-changes ...informe-o em detalhes exaustivos, embora concisos.

Responder3

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 --attributes-onlya opção do GNU cp, junto com --archive, como é um código testado e comprovado, executa 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/

Tal como acontece com os arquivos, cpé aditivo com atributos estendidos: se a origem e o destino tiverem atributos estendidos,adicionaos atributos estendidos da origem para o destino (em vez de excluir primeiro todos os xattrs do destino). Embora isso espelhe o cpcomportamento 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 da primeira vez, rsyncmas deseja preservá-los agora, entãocp não vaiconserte isso para você; provavelmente é melhor você executar novamente rsynccom as opções certas (veja meuoutra resposta) e ser paciente.

Se você encontrou esta pergunta enquanto procuravadeliberadamenteseparar e recombinar metadados/conteúdo de arquivo, então você pode querer dar uma olhada emmetastoreque está nos repositórios do Ubuntu.

Fonte:Manual do GNU coreutils


Editado para adicionar:

cpdo GNU coreutils>= 8.17 e superior funcionarão conforme descrito, mas coreutils <= 8.16 truncará arquivos ao restaurar seus metadados. Em caso de dúvida, não utilize cpnesta situação; usar rsynccomas opções certase/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 oTruque 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);
}

Responder4

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

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

informação relacionada