Diferenciando dois grandes arquivos de texto

32

Eu tenho dois arquivos grandes (6 GB cada). Eles não são classificados, com alimentações de linha ( \n) como separadores. Como posso diferenciá-los? Deve demorar menos de 24h.

jonasl
fonte

Respostas:

45

A resposta mais óbvia é apenas usar o comando diff e provavelmente é uma boa ideia adicionar o parâmetro --speed-large-files a ele.

diff --speed-large-files a.file b.file

Como você menciona arquivos não classificados, talvez seja necessário classificá-los primeiro

sort a.file > a.file.sorted
sort b.file > b.file.sorted
diff --speed-large-files a.file.sorted b.file.sorted

você pode salvar a criação de um arquivo de saída extra canalizando a saída de 2ª ordem diretamente para o diff

sort a.file > a.file.sorted
sort b.file | diff --speed-large-files a.file.sorted -

Obviamente, eles funcionarão melhor em um sistema com muita memória disponível e você provavelmente precisará de muito espaço livre em disco também.

Não ficou claro em sua pergunta se você já tentou isso antes. Nesse caso, seria útil saber o que deu errado (demorou muito, etc.). Sempre achei que os comandos de classificação e difusão de ações tendem a executar pelo menos tão bem quanto os comandos personalizados, a menos que existam algumas propriedades específicas dos domínios dos arquivos que possibilitem fazer as coisas de maneira diferente.

Richm
fonte
2
+1. Você pode omitir todos os arquivos temporários com pipes nomeados. Use mkfifopara criar [ab].file.sortedantes de usá-los como saída para sort. Coloque ambos sorts com &em segundo plano e use os dois tubos como nomes de arquivos para diff.
krissi
15
@krissi Você também pode obter o mesmo efeito usando esta sintaxe:diff <(command 1) <(command 2)
Michael Mrozek
Graças trabalhou. Eu precisava de um par de GB de pensamento memória, mas uma instância de 16GB Amazon EC2 fixa-lo :)
jonasl
7
Se alguém como eu se perguntar por que a <(cmd1) <(cmd2)sintaxe funciona (como parece redirecionar a entrada padrão duas vezes!), Tente echo hello <(cmd1) <(cmd2). Você vai ver algo como hello /dev/fd/63 /dev/fd/62que de repente deixa claro;)
alex
3
Na minha experiência, a --speed-large-filesopção não ajuda se você não tiver RAM suficiente. Além disso, a pré-classificação não é útil se você tiver uma estrutura de registros com várias linhas que deseja preservar. As opções mencionadas acima (por @unhammer) são interessantes, mas a saída rdiffe bsdiffé bastante binária. Instalar a bdiffpartir da Caixa de ferramentas do Heirloom parece uma tarefa assustadora (requer devtools do Heirloom, arquivos de cabeçalho extintos, ...). Realmente vale o esforço? Existem outras alternativas?
Christian Pietsch
5

Classificar as entradas e informar ao diffprograma que as entradas são classificadas proporcionaria uma grande velocidade. Eu não conheço nenhum diffcom uma opção como essa, mas commassume entradas classificadas e será muito mais rápido se fizer o suficiente para seus propósitos.

Karl
fonte
commfuncionou muito bem para isso, nunca ouvi falar disso antes, mas aparentemente está em coreutils.
theferrit32 16/11