Como sincronizar duas pastas com ferramentas de linha de comando?

63

Depois de migrar para o Linux a partir do Windows, gostaria de encontrar um software alternativo para o Winmerge ou, melhor ainda, aprender ferramentas de linha de comando para comparar e sincronizar duas pastas no Linux. Ficaria muito grato se você pudesse me dizer como executar as seguintes tarefas na linha de comando ... (Estudei diff e rsync, mas ainda preciso de ajuda.)

Temos duas pastas: "/ home / user / A" e "/ home / user / B"

A pasta A é o local em que arquivos e pastas regulares são salvos e a pasta B é uma pasta de backup que serve como um espelho completo da pasta A. (Nada é salvo ou modificado diretamente pelo usuário na pasta B.)

Minhas perguntas são:

  • Como listar arquivos que existem apenas na pasta B? (Por exemplo, os excluídos da pasta A desde a última sincronização.)

  • Como copiar arquivos que existem apenas na pasta B novamente na pasta A?

  • Como listar os arquivos existentes nas duas pastas, mas com carimbos de data e hora diferentes? (Os que foram modificados na pasta A desde a última sincronização. Gostaria de evitar o uso de somas de verificação, porque existem dezenas de milhares de arquivos e isso tornaria o processo muito lento.)

  • Como fazer uma cópia exata da pasta A na pasta B? Quero dizer, copie tudo da pasta A para a pasta B que existe apenas na pasta A e exclua tudo da pasta B que existe apenas na pasta B, mas sem tocar nos arquivos iguais nas duas pastas.

akopacsi
fonte
Por que não usar um programa de backup adequado para isso? Duplicidade é um exemplo.
Qudit

Respostas:

88

Isso coloca a pasta A na pasta B:

rsync -avu --delete "/home/user/A" "/home/user/B"  

Se você deseja que o conteúdo das pastas A e B seja o mesmo, coloque /home/user/A/(com a barra) a fonte. Isso não pega a pasta A, mas todo o seu conteúdo e coloca-a na pasta B. Assim:

rsync -avu --delete "/home/user/A/" "/home/user/B"
  • -a Faça a sincronização preservando todos os atributos do sistema de arquivos
  • -v executar verbalmente
  • -u somente copie arquivos com uma hora de modificação mais recente (ou diferença de tamanho se os horários forem iguais)
  • --delete exclua os arquivos na pasta de destino que não existem na fonte

Página de manual: https://download.samba.org/pub/rsync/rsync.html

TuxForLife
fonte
7
rsync : execute o aplicativo rsync, -a : faça a sincronização preservando todos os atributos do sistema de arquivos, -v : execute verbalmente, -z : comprima os dados durante a sincronização (transporte os dados no modo compactado), --delete : exclua os arquivos no destino pasta que não existam na origem, / home / user / a : pasta de origem, / home / user / B : pasta de destino
SonicARG
Olá SonicARG, esqueci totalmente de voltar a isso e colocar a explicação, obrigado enviando a explicação, eu coloquei a sua na resposta, espero que você não se importe.
TuxForLife 11/07/16
6
O Rsync tem como principal objetivo copiar arquivos entre computadores diferentes, conforme explicado aqui, ele pode servir também para sincronizar diretórios. Portanto, a opção -z é interessante para reduzir o tráfego de rede e, assim, melhorar o desempenho de um rsync entre 2 computadores: (ler dados do disco -> compactar) === rede ===> (descompactar> gravar no disco) Usando - z para sincronizar 2 diretórios no mesmo host é um pouco bobo e desperdício de ciclos de CPU que você obteria (ler dados do disco -> compressa -> uncompress -> gravação para o disco)
GerritCap
@GerritCap, fiz uma edição, obrigado pela sua valiosa contribuição
TuxForLife
11
Eu tentei o comando, mas ele criou um subdiretório em /home/user/B/Avez de substituir o conteúdo de A pelo conteúdo de B. Você poderia me ajudar a dar uma olhada?
Luke
10

Você poderia unisonferramenta desenvolvida por Benjamin Pierce na U Penn.

Vamos supor que você tenha dois diretórios,

/home/user/Documents/dirA/ e /home/user/Documents/dirB/

Para sincronizar esses dois, você pode usar:

~ $unison -ui text /home/user/Documents/dirA/ /home/user/Documents/dirB/

Na saída, unisonexibirá todos os diretórios e arquivos diferentes nos dois diretórios que você pediu para sincronizar. Ele recomendará sincronizar (replicar o arquivo ausente nos dois locais) de forma aditiva na execução inicial, criar e manter uma árvore de sincronização em sua máquina e, nas execuções subsequentes, implementará a sincronização verdadeira (ou seja, se você excluir um arquivo .../dirA, vai ficar excluído do .../dirBbem. Você também pode comparar cada mudança e, opcionalmente, optar por encaminhar ou reverter sincronizar entre os dois diretórios.

Opcionalmente, para iniciar a interface gráfica, basta remover a -ui textopção do seu comando, embora eu ache o climais simples e rápido de usar.

Mais sobre isso: tutorial do Unison na documentação do usuário do Unison .

Aalok
fonte
1

A resposta do TuxForLife é muito boa, mas eu sugiro que você use -cao sincronizar localmente. Você pode argumentar que não vale a pena a penalidade de tempo / rede para fazer sincronizações remotas, mas vale totalmente a pena para arquivos locais, porque a velocidade é muito alta.

-c, --checksum
       This forces the sender to checksum every regular file using a 128-bit  MD4
       checksum.   It  does this during the initial file-system scan as it builds
       the list of all available files. The receiver then checksums  its  version
       of  each  file  (if  it exists and it has the same size as its sender-side
       counterpart) in order to decide which files need to be updated: files with
       either  a  changed  size  or a changed checksum are selected for transfer.
       Since this whole-file checksumming of all files on both sides of the  con-
       nection  occurs  in  addition to the automatic checksum verifications that
       occur during a file's transfer, this option can be quite slow.

       Note that rsync always verifies that each transferred file  was  correctly
       reconstructed  on  the receiving side by checking its whole-file checksum,
       but that automatic after-the-transfer verification has nothing to do  with
       this  option's  before-the-transfer  "Does  this file need to be updated?"
       check.

Isso mostra como ter o mesmo tamanho e carimbos de hora pode falhar.

A configuração

$ cd /tmp

$ mkdir -p {A,b}/1/2/{3,4}

$ echo "\___________from A" | \
      tee A/1/2/x  | tee A/1/2/3/y  | tee A/1/2/4/z  | \
  tr A b | \
      tee b/1/2/x  | tee b/1/2/3/y  | tee b/1/2/4/z  | \
      tee b/1/2/x0 | tee b/1/2/3/y0 >     b/1/2/4/z0

$ find A b -type f | xargs -I% sh -c "echo %; cat %;"
A/1/2/3/y
\___________from A
A/1/2/4/z
\___________from A
A/1/2/x
\___________from A
b/1/2/3/y
\___________from b
b/1/2/3/y0
\___________from b
b/1/2/4/z
\___________from b
b/1/2/4/z0
\___________from b
b/1/2/x
\___________from b
b/1/2/x0
\___________from b

O rsync que não copia nada porque todos os arquivos têm o mesmo tamanho e carimbo de data e hora

$ rsync -avu A/ b
building file list ... done

sent 138 bytes  received 20 bytes  316.00 bytes/sec
total size is 57  speedup is 0.36

$ find A b -type f | xargs -I% sh -c "echo %; cat %;"
A/1/2/3/y
\___________from A
A/1/2/4/z
\___________from A
A/1/2/x
\___________from A
b/1/2/3/y
\___________from b
b/1/2/3/y0
\___________from b
b/1/2/4/z
\___________from b
b/1/2/4/z0
\___________from b
b/1/2/x
\___________from b
b/1/2/x0
\___________from b    

O rsync que funciona corretamente porque compara somas de verificação

$ rsync -cavu A/ b
building file list ... done
1/2/x
1/2/3/y
1/2/4/z

sent 381 bytes  received 86 bytes  934.00 bytes/sec
total size is 57  speedup is 0.12

$ find A b -type f | xargs -I% sh -c "echo %; cat %;"
A/1/2/3/y
\___________from A
A/1/2/4/z
\___________from A
A/1/2/x
\___________from A
b/1/2/3/y
\___________from A
b/1/2/3/y0
\___________from b
b/1/2/4/z
\___________from A
b/1/2/4/z0
\___________from b
b/1/2/x
\___________from A
b/1/2/x0
\___________from b
Bruno Bronosky
fonte
-c e -u funcionam bem juntos?
Sergey Korzhov
@SergeyKorzhov faz. O `-u 'ainda funciona como de costume para atualizar apenas se o destino não for mais novo.
Bruno Bronosky 15/07
1

É isso que estou usando para fazer backup de arquivos pessoais, nos quais não me importo com tudo o que é coberto -ae quero que informações mais úteis sejam impressas.

rsync -rtu --delete --info=del,name,stats2 "/home/<user>/<src>/" "/run/media/<user>/<drive>/<dst>"

Na página do manual rsync :

-r, --recursive
Isso diz ao rsync para copiar diretórios recursivamente.

-t, --times
Diz ao rsync para transferir os tempos de modificação junto com os arquivos e atualizá-los no sistema remoto.

-u, --update
Isso força o rsync a ignorar qualquer arquivo existente no destino e ter um horário modificado mais recente que o arquivo de origem. (Se um arquivo de destino existente tiver um tempo de modificação igual ao do arquivo de origem, ele será atualizado se os tamanhos forem diferentes.)

--delete
Diz ao rsync para excluir arquivos estranhos do lado de recebimento (aqueles que não estão no lado de envio), mas apenas para os diretórios que estão sendo sincronizados.

--info = FLAGS
Esta opção permite que você tenha controle refinado sobre a saída de informações que deseja ver.

De rsync --info=help

DEL        Mention deletions on the receiving side  
NAME       Mention 1) updated file/dir names, 2) unchanged names  
STATS      Mention statistics at end of run (levels 1-3)

Embora menos explícito, isso é aparentemente equivalente e mais curto:

rsync -rtuv --delete --info=stats2 "/home/<user>/<src>/" "/run/media/<user>/<drive>/<dst>"

-v, --verbose
Um único -v fornece informações sobre quais arquivos estão sendo transferidos e um breve resumo no final [stats1].

Honesto Abe
fonte
0

Não é exatamente o mesmo que você solicita, mas você pode considerar usar uma ferramenta de controle de versão. Ferramentas como o Git fazem tudo o que você pede e muito mais, especialmente se você não trabalha diretamente na pasta B, pode ser interessante dar uma olhada. você pode encontrar mais informações sobre o git aqui

switch87
fonte
2
Isso só funciona se você deseja adicionar tudo ao controle de versão. Também força todas as alterações já comprometidas a serem armazenadas permanentemente, o que pode ser indesejável.
Qudit
@Qudit, isso é verdade, embora seja possível via clonagem limitar o histórico, mas a limitação do histórico ainda não está implementada no Git por padrão.
switch87
@ switch87 Sim, eu sei que você pode excluir confirmações antigas. O controle de versão não é realmente uma solução apropriada para backups genéricos, especialmente se houver arquivos binários grandes.
Qudit
Sua pergunta é para backup local, mas se você o usar para backup remoto, ainda poderá usar o anexo git para os arquivos maiores. para backup local, isso não é um problema.
Switch87
2
@ switch87 Isso realmente deveria ter sido um comentário ao Q e não uma resposta, pois não explica como você usaria o git para fazer backups.
Slm
0

Você pode usá-lo desta maneira:

rsync -avu --delete /home/user/A/* /home/user/B/

Dessa forma, você copiará o conteúdo da pasta A para a pasta B, não o conteúdo da própria pasta A.

Isaias Sanchez
fonte