Tentei o diff, mas ele gera alguns números e outros símbolos na frente de linhas diferentes, o que torna difícil para mim comparar os arquivos.
Dom
Respostas:
216
diff (1) não é a resposta, mas comm (1) é.
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
assim
comm -2-3 file1 file2 > file3
Os arquivos de entrada devem ser classificados. Se não forem, classifique-os primeiro. Isso pode ser feito com um arquivo temporário ou ...
comm -2-3<(sort file1)<(sort file2)> file3
desde que seu shell suporte substituição de processo (bash faz).
Lembre-se de que dois arquivos devem ser classificados e são únicos
andy
6
Você pode agrupar as opções:comm -23
Paolo M
O que significa "classificado"? Que as linhas têm a mesma ordem? Então, provavelmente, é adequado para a maioria dos casos de uso - como em, verificar quais linhas foram adicionadas comparando com uma versão anterior com backup. Se as linhas recém-adicionadas não podem estar entre as linhas existentes, isso é mais um problema.
Egor Hans
@EgorHans: se o arquivo tiver, por exemplo, linhas contendo inteiros como "3 \ n1 \ n3 \ n2 \ n", as linhas devem primeiro ser reordenadas em ordem crescente ou decrescente, por exemplo, "\ 1 \ n2 \ n3 \ n3 \ n" com duplicatas adjacente. Isso é "classificado" e ambos os arquivos devem ser classificados de maneira semelhante. Quando o arquivo mais recente tem novas linhas, não importa se elas estão "entre as linhas existentes" porque depois da classificação não estão, elas estão em ordem de classificação.
sorpigal
48
O utilitário Unix diffé feito exatamente para esse propósito.
$ diff -u file1 file2 > file3
Consulte o manual e a Internet para opções, diferentes formatos de saída, etc.
Isso não cumpre o trabalho solicitado; ele insere um monte de caracteres extras, mesmo com o uso de opções de linha de comando sugeridas em outras respostas.
xenocyon
20
Considere o seguinte:
arquivo a.txt:
abcd
efgh
arquivo b.txt:
abcd
Você pode encontrar a diferença com:
diff -a --suppress-common-lines -y a.txt b.txt
O resultado será:
efgh
Você pode redirecionar a saída em um arquivo de saída (c.txt) usando:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
Isso vai responder à sua pergunta:
"... que contém as linhas no arquivo1 que não estão presentes no arquivo2."
Existem duas limitações para esta resposta: (1) só funciona para linhas curtas (menos de 80 caracteres por padrão, embora isso possa ser modificado) e, mais importante, (2) adiciona um "<" no final de cada linha que deve ser retirada com outro programa (por exemplo, awk, sed).
sergut
Em muitos casos, você também desejará usar -d, o que fará diffo possível para encontrar a menor diferença possível. -i, -E, -w, -BE --suppress-blank-emptypode também ser útil, ocasionalmente, embora não sempre. Se você não sabe o que se encaixa no seu caso de uso, tente diff --helpprimeiro (o que geralmente é uma boa ideia quando você não sabe o que um comando pode fazer).
Egor Hans
Além disso, usando --line-format =% L, você evita que o diff gere quaisquer caracteres extras (pelo menos, a ajuda diz que funciona assim, ainda prestes a experimentá-lo).
Às vezes diffé o utilitário de que você precisa, mas às vezes joiné mais apropriado. Os arquivos precisam ser pré-classificados ou, se você estiver usando um shell que suporte a substituição de processos, como bash, ksh ou zsh, você pode fazer a classificação em tempo real.
Você deveria ganhar uma medalha por isso! Era exatamente o que eu estava procurando nas últimas 2 horas
Zatarra
7
Experimentar
sdiff file1 file2
Normalmente funciona muito melhor na maioria dos casos para mim. Você pode querer classificar os arquivos antes, se a ordem das linhas não for importante (por exemplo, alguns arquivos de configuração de texto).
Belo utilitário! Eu amo como isso marca as linhas de diferenciação. Torna muito mais fácil comparar configurações. Isso junto com o tipo é uma combinação mortal (por exemplo sdiff <(sort file1) <(sort file2))
jmagnusson
3
Se você precisa resolver isso com coreutils, a resposta aceita é boa:
comm -23<(sort file1)<(sort file2)> file3
Você também pode usar sd (stream diff), que não requer classificação nem substituição de processo e suporta fluxos infinitos, assim:
cat file1 | sd 'cat file2'> file3
Provavelmente não é um grande benefício neste exemplo, mas ainda considere isso; em alguns casos você não poderá usar commnem grep -Fnem diff.
Aqui está uma postagem de blog que escrevi sobre diffing streams no terminal, que apresenta o sd.
Muitas respostas já, mas nenhuma delas IMHO perfeito. A resposta de Thanatos deixa alguns caracteres extras por linha e a resposta de Sorpigal exige que os arquivos sejam classificados ou pré-classificados, o que pode não ser adequado em todas as circunstâncias.
Acho que a melhor maneira de obter as linhas que são diferentes e nada mais (não caracteres extras, sem re-ordenação) é uma combinação de diff, grepeawk (ou similar).
Se as linhas não contêm nenhum "<", uma linha curta pode ser:
diff urls.txt*| grep "<"| sed 's/< //g'
mas isso removerá todas as instâncias de "<" (menos que, espaço) das linhas, o que nem sempre está OK (por exemplo, código-fonte). A opção mais segura é usar o awk:
Este one-liner diffs ambos os arquivos, então filtra a saída do estilo ed do diff, então remove o "<" que o diff adiciona. Isso funciona mesmo se as linhas contiverem alguns "<".
Tentei quase todas as respostas neste tópico, mas nenhuma foi completa. Depois de algumas trilhas acima, uma funcionou para mim. diff lhe dará diferença, mas com alguns charas especiais indesejados. onde suas linhas de diferença reais começam com '>'. então o próximo passo é fazer o grep das linhas começar com '>' e, em seguida, remover as mesmas com sed .
Esta é uma má ideia. Você também precisaria modificar as linhas começando com <. Você verá isso se trocar a ordem dos arquivos de entrada. Mesmo se você fizesse isso, você iria querer omitir grepusando mais sed: `diff a1 a2 | sed '/> / s ///' `Isso ainda pode quebrar linhas contendo >ou <na situação certa e ainda deixa linhas extras descrevendo os números das linhas. Se você queria experimentar esta abordagem uma maneira melhor seria: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'.
sorpigal
0
Você pode usar diffcom a seguinte formatação de saída:
--old-line-format='', desabilite a saída para arquivo1 se a linha for diferente compare em arquivo2. --unchanged-line-format='', desative a saída se as linhas forem iguais.
Respostas:
diff (1) não é a resposta, mas comm (1) é.
assim
Os arquivos de entrada devem ser classificados. Se não forem, classifique-os primeiro. Isso pode ser feito com um arquivo temporário ou ...
desde que seu shell suporte substituição de processo (bash faz).
fonte
comm -23
O utilitário Unix
diff
é feito exatamente para esse propósito.Consulte o manual e a Internet para opções, diferentes formatos de saída, etc.
fonte
Considere o seguinte:
arquivo a.txt:
arquivo b.txt:
Você pode encontrar a diferença com:
O resultado será:
Você pode redirecionar a saída em um arquivo de saída (c.txt) usando:
Isso vai responder à sua pergunta:
fonte
-d
, o que farádiff
o possível para encontrar a menor diferença possível.-i
,-E
,-w
,-B
E--suppress-blank-empty
pode também ser útil, ocasionalmente, embora não sempre. Se você não sabe o que se encaixa no seu caso de uso, tentediff --help
primeiro (o que geralmente é uma boa ideia quando você não sabe o que um comando pode fazer).Às vezes
diff
é o utilitário de que você precisa, mas às vezesjoin
é mais apropriado. Os arquivos precisam ser pré-classificados ou, se você estiver usando um shell que suporte a substituição de processos, como bash, ksh ou zsh, você pode fazer a classificação em tempo real.fonte
Experimentar
Normalmente funciona muito melhor na maioria dos casos para mim. Você pode querer classificar os arquivos antes, se a ordem das linhas não for importante (por exemplo, alguns arquivos de configuração de texto).
Por exemplo,
fonte
sdiff <(sort file1) <(sort file2)
)Se você precisa resolver isso com coreutils, a resposta aceita é boa:
Você também pode usar sd (stream diff), que não requer classificação nem substituição de processo e suporta fluxos infinitos, assim:
Provavelmente não é um grande benefício neste exemplo, mas ainda considere isso; em alguns casos você não poderá usar
comm
nemgrep -F
nemdiff
.Aqui está uma postagem de blog que escrevi sobre diffing streams no terminal, que apresenta o sd.
fonte
Ainda assim, nenhuma
grep
solução?linhas que existem apenas no arquivo 2:
linhas que existem apenas no arquivo 1:
linhas que existem em ambos os arquivos:
fonte
Muitas respostas já, mas nenhuma delas IMHO perfeito. A resposta de Thanatos deixa alguns caracteres extras por linha e a resposta de Sorpigal exige que os arquivos sejam classificados ou pré-classificados, o que pode não ser adequado em todas as circunstâncias.
Acho que a melhor maneira de obter as linhas que são diferentes e nada mais (não caracteres extras, sem re-ordenação) é uma combinação de
diff
,grep
eawk
(ou similar).Se as linhas não contêm nenhum "<", uma linha curta pode ser:
mas isso removerá todas as instâncias de "<" (menos que, espaço) das linhas, o que nem sempre está OK (por exemplo, código-fonte). A opção mais segura é usar o awk:
Este one-liner diffs ambos os arquivos, então filtra a saída do estilo ed do diff, então remove o "<" que o diff adiciona. Isso funciona mesmo se as linhas contiverem alguns "<".
fonte
Eu não sou ninguém surpreso mencionado
diff -y
para produzir uma saída de side-by-side , por exemplo:E em
file3
(as diferentes linhas têm um símbolo|
no meio):fonte
Use o utilitário Diff e extraia apenas as linhas que começam com <na saída
fonte
Tentei quase todas as respostas neste tópico, mas nenhuma foi completa. Depois de algumas trilhas acima, uma funcionou para mim. diff lhe dará diferença, mas com alguns charas especiais indesejados. onde suas linhas de diferença reais começam com '>'. então o próximo passo é fazer o grep das linhas começar com '>' e, em seguida, remover as mesmas com sed .
fonte
<
. Você verá isso se trocar a ordem dos arquivos de entrada. Mesmo se você fizesse isso, você iria querer omitirgrep
usando mais sed: `diff a1 a2 | sed '/> / s ///' `Isso ainda pode quebrar linhas contendo>
ou<
na situação certa e ainda deixa linhas extras descrevendo os números das linhas. Se você queria experimentar esta abordagem uma maneira melhor seria:diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.Você pode usar
diff
com a seguinte formatação de saída:--old-line-format=''
, desabilite a saída para arquivo1 se a linha for diferente compare em arquivo2.--unchanged-line-format=''
, desative a saída se as linhas forem iguais.fonte