Como você compara duas pastas e copia a diferença para uma terceira pasta?

23

Você tem três pastas:

  • pasta atual , que contém seus arquivos atuais
  • pasta antiga , que contém uma versão mais antiga dos mesmos arquivos
  • diferença de pasta , que é apenas uma pasta vazia

Como você compara o antigo com o atual e copia os arquivos que são diferentes (ou inteiramente novos) da atual para a diferença ?


Eu pesquisei ao redor e parece uma coisa simples de resolver, mas não consigo fazê-lo funcionar no meu exemplo particular. A maioria das fontes sugeriu o uso do rsync, então acabei com o seguinte comando:

rsync -ac --compare-dest=../old/ new/ difference/

O que isso faz, no entanto, é copiar todos os arquivos de novos para diferentes , mesmo aqueles que são iguais aos antigos .

Caso isso ajude (talvez o comando esteja correto e a falha esteja em outro lugar), foi assim que eu testei isso:

  1. Eu fiz as três pastas.
  2. Criei vários arquivos de texto com conteúdos diferentes no passado .
  3. Copiei os arquivos do antigo para o novo .
  4. Alterei o conteúdo de alguns arquivos em novo e adicionei alguns arquivos adicionais.
  5. Eu executei o comando acima e verifiquei os resultados em diferença .

Estive procurando uma solução nos últimos dois dias e realmente aprecio alguma ajuda. Não precisa necessariamente estar usando o rsync, mas eu gostaria de saber o que estou fazendo de errado, se possível.

Thane
fonte
possível duplicação de Como salvar arquivos alterados?
wingedsubmariner
@wingedsubmariner Não acho que seja uma duplicata, pois a resposta aceita na pergunta vinculada é o comando sobre o qual o OP está fazendo uma pergunta.
Bernhard
@ Bernhard Ah, meu mal. Acho que não entendi a pergunta original.
wingedsubmariner
@wingedsubmariner Não se preocupe, você disse "possível", e eu concordo que parece muito semelhante :)
Bernhard

Respostas:

7

Não tenho certeza se você pode fazê-lo com qualquer comando linux existente, como rsync ou diff. Mas, no meu caso, tive que escrever meu próprio script usando Python, pois o python possui o módulo "filecmp" para comparação de arquivos. Publiquei todo o script e uso em meu site pessoal - http://linuxfreelancer.com/

Seu uso é simples - forneça o caminho absoluto do novo diretório, diretório antigo e diretório de diferenças nessa ordem.

#!/usr/bin/env python

import os, sys
import filecmp
import re
from distutils import dir_util
import shutil
holderlist=[]

def compareme(dir1, dir2):
    dircomp=filecmp.dircmp(dir1,dir2)
    only_in_one=dircomp.left_only
    diff_in_one=dircomp.diff_files
    dirpath=os.path.abspath(dir1)
    [holderlist.append(os.path.abspath( os.path.join(dir1,x) )) for x in only_in_one]
    [holderlist.append(os.path.abspath( os.path.join(dir1,x) )) for x in diff_in_one]
    if len(dircomp.common_dirs) > 0:
        for item in dircomp.common_dirs:
            compareme(os.path.abspath(os.path.join(dir1,item)), os.path.abspath(os.path.join(dir2,item)))
        return holderlist

def main():
 if len(sys.argv) > 3:
   dir1=sys.argv[1]
   dir2=sys.argv[2]
   dir3=sys.argv[3]
 else:
   print "Usage: ", sys.argv[0], "currentdir olddir difference"
   sys.exit(1)

 if not dir3.endswith('/'): dir3=dir3+'/'

 source_files=compareme(dir1,dir2)
 dir1=os.path.abspath(dir1)
 dir3=os.path.abspath(dir3)
 destination_files=[]
 new_dirs_create=[]
 for item in source_files:
   destination_files.append(re.sub(dir1, dir3, item) )
 for item in destination_files:
  new_dirs_create.append(os.path.split(item)[0])
 for mydir in set(new_dirs_create):
   if not os.path.exists(mydir): os.makedirs(mydir)
#copy pair
 copy_pair=zip(source_files,destination_files)
 for item in copy_pair:
   if os.path.isfile(item[0]):
    shutil.copyfile(item[0], item[1])

if __name__ == '__main__':
 main()
Daniel t.
fonte
21

Eu descobri qual era o problema no meu caso:

Os arquivos que eu estava comparando tinham timestamps diferentes. Eu não deveria ter usado o argumento -a , presumo que o rsync estava tentando preservar os carimbos de data e hora ao copiar arquivos. O comando que funcionou para mim foi:

rsync -rvcm --compare-dest=../old/ new/ difference/
Thane
fonte
Penso que para testar isso com a opção -a (archive), você deveria ter usado rsync -apara "copiar" os arquivos inicialmente (ou o equivalente em cp) e depois excluído ou modificado. (Gosto de manter o rsync porque sei que é auto-consistente sem pensar no que pode estar fazendo.) Acho que deveria ter funcionado com o comando original. A opção -a inclui -t (comparar por carimbo de data / hora), que é a alternativa para -c (comparar por soma de verificação).
sálvia
2
Na minha opinião, essa resposta deve ser a mais aceita, pois é muito mais simples. Além disso, o comando só funcionou para mim quando forneci o caminho completo para old/e new/.
Yamaneko
A ressalva parece ser que o valor de comparação deve ser o caminho relativo para a diferença, visto de dentro do destino real
Ryan Williams
1

Isso pode ajudar alguns leitores: No Windows, um pequeno programa mais antigo e gratuito - Third Dir - faz exatamente o que está sendo solicitado aqui. Já não está disponível através do desenvolvedor, Robert Vašíček. Mas tenho certeza que pode ser encontrado através de alguns repositórios online.

Aqui está a descrição do desenvolvedor, que permanece em seu site:

Terceiro diretório: um incomum sincronizador de diretório - os diferentes arquivos são copiados para o terceiro diretório. É muito útil extrair, por exemplo, fotos novas ou editadas de uma grande árvore de diretórios no disco fixo para uma pasta temporária e adicioná-las ao CD de arquivo (nota - os arquivos originais são comparados com o CD). Versão 1.4, tamanho 23kB. Criado 2005-02-12.

Histórico: Versão 1.14 - Mais eficiente quando são comparados muitos dez dos milhares de arquivos.

Steve
fonte
0

A maneira rsync dada por Thane com as adições de Yamaneko funciona muito bem, mas deixa diretórios vazios. Para mim, a solução final foi em duas etapas, primeiro chame o rsync com caminho completo e, em seguida, um comando find para remover todos os diretórios vazios:

rsync -rvcm --compare-dest=/tmp/org/ /tmp/new/ /tmp/difference/
find /tmp/difference/ -d -type d -empty -exec rmdir {} \; -print

Observe que mesmo com a opção --links, o rsync não manteve links simbólicos, mas copiou os dados de destino.

PierreL
fonte
Observe que, em vez de -empty -exec rmdir {} \;você pode usar -empty -delete.
mivk 2/07
-3

Eu uso o dualpane XY Explorer (comercial), que pode fazer muitos truques e esse é um deles. Abra Currentem um painel e Antigo no outro. Ative o painel Atual. Vá para Painéis > Seleção de sincronização . Oferece 5 opções para você selecionar:

  1. Jogos (listados em ambos)
  2. Exclusivos (no painel ativo)
  3. Mais recente (no painel ativo)
  4. Arquivos exclusivos e mais recentes (no painel ativo)
  5. Selecionado (aqueles selecionados no outro painel)

Agora você pode copiar a seleção resultante de Currentonde quiser. Usei-o para comparar mailfoldersas instalações antigas com as mais recentes. A estrutura da pasta era bastante complexa, mas (quase) todas mbs-filestinham um número único.

Por isso, fiz uma pesquisa na mbs-filesraiz antiga mailfolder(em um painel) e na mais nova (no outro painel) e fiz uma comparação nos resultados da pesquisa em cada painel ( Seleção de sincronização exclusiva) , para encontrar e-mails perdidos durante reinstala)! Você também pode definir muitas opções.

Martijn Douwes
fonte
1
Se você estiver falando de software não padrão, inclua um link. Se você quer dizer que o XYplorer não ajudará o OP de maneira alguma.
Anthon