Eu tenho dois arquivos de texto e quero encontrar as diferenças entre eles usando o Windows Powershell. Existe algo semelhante à ferramenta de comparação do Unix disponível? Ou existe outra maneira que não considerei?
Eu tentei comparar-object, mas obtive esta saída enigmática:
PS C:\> compare-object one.txt two.txt
InputObject SideIndicator
----------- -------------
two.txt =>
one.txt <=
Eu mesmo descobri. Como o Powershell funciona com objetos .net em vez de texto, você precisa usar get-content para expor o conteúdo dos arquivos de texto. Então, para executar o que eu estava tentando fazer na pergunta, use:
Uma maneira mais simples de fazer isso é escrever:
Ou você pode usar o comando DOS
fc
assim (Isso mostra a saída de ambos os arquivos, então você terá que verificar as diferenças):fc
é um alias para o cmdlet Format-Custom, portanto, certifique-se de inserir o comando comofc.exe
. Observe que muitos utilitários do DOS não lidam com a codificação UTF-8.Você também pode gerar um processo CMD e executá
fc
-lo.Isso instrui o PowerShell a iniciar um processo com o programa 'cmd' usando os parâmetros entre aspas. Nas aspas, está a opção '/c' cmd para executar o comando e encerrar. O comando real a ser executado pelo cmd no processo está
fc filea.txt fileb.txt
redirecionando a saída para o arquivodiff.txt
.Você pode usar o DOS
fc.exe
de dentro do powershell.diff em *nix não faz parte do shell, mas um aplicativo separado.
Existe algum motivo pelo qual você não pode usar o diff.exe no PowerShell?
Você pode baixar uma versão do pacote UnxUtils ( http://unxutils.sourceforge.net/ )
compare-object (também conhecido como diff alias) é patético se você espera que ele se comporte como um diff unix. Eu tentei o diff (gc file1) (gc file2), e se uma linha for muito longa, não consigo ver o diff real e, mais importante, não posso dizer em qual número de linha o diff está.
Quando tento adicionar -passthru, agora posso ver a diferença, mas perco em qual arquivo a diferença está e ainda não recebo um número de linha.
Meu conselho, não use o powershell para encontrar diferenças nos arquivos. Como alguém observou, fc funciona e funciona um pouco melhor do que compare-object, e ainda melhor é baixar e usar ferramentas reais como o emulador unix que Mikeage mencionou.
WinMerge é outra boa ferramenta de comparação baseada em GUI.
Como outros notaram, se você estivesse esperando uma saída de diff unix-y, usar o alias de diff powershell o decepcionaria. Por um lado, você tem que segurar a mão na leitura de arquivos (com gc / get-content). Por outro lado, o indicador de diferença está à direita, longe do conteúdo - é um pesadelo de legibilidade.
A solução para quem procura uma saída sã é
adicione a linha
O argumento -force é necessário porque o Powershell é bastante precioso sobre esse alias embutido específico. Se alguém estiver interessado em ter o GnuWin32 instalado, também incluo o seguinte no meu perfil do powershell:
Principalmente porque o Powershell não entende argumentos que são executados juntos e digitados, por exemplo, "rm -Force -Recurse" é muito mais trabalhoso do que "rm -rf".
O Powershell tem alguns recursos interessantes, mas há algumas coisas que ele não deveria tentar fazer por mim.
fc.exe
é melhor para comparação de texto, pois foi projetado para funcionar como *nix diff, ou seja, compara linhas sequencialmente, mostrando as diferenças reais e tentando sincronizar novamente (se as diferentes seções tiverem comprimentos diferentes). Ele também tem algumas opções de controle úteis (texto/binário, diferenciação de maiúsculas e minúsculas, números de linha, comprimento de ressincronização, tamanho do buffer incompatível) e fornece status de saída (-1 sintaxe incorreta, 0 arquivos iguais, 1 arquivo diferente, 2 arquivos ausentes). Sendo um utilitário DOS (muito) antigo, ele tem algumas limitações. Mais notavelmente, ele não funciona automaticamente com Unicode, tratando o 0 MSB de caracteres ASCII como um terminador de linha para que o arquivo se torne uma sequência de linhas de 1 caractere (@kennycoc: use a opção /U para especificar AMBOS os arquivos são Unicode, WinXP em diante ) e também tem um tamanho de buffer de linha dura de 128 caracteres (128 bytes ASCII,compare-object é projetado para determinar se 2 objetos são idênticos em membros. se os objetos são coleções, então eles são tratados como SETS (veja a ajuda compare-object), ou seja, coleções UNORDERED sem duplicatas. 2 conjuntos são iguais se tiverem os mesmos itens de membro, independentemente da ordem ou duplicações. Isso limita severamente sua utilidade para comparar arquivos de texto para diferenças. Em primeiro lugar, o comportamento padrão coleta as diferenças até que todo o objeto (arquivo = array de strings) tenha sido verificado, perdendo assim a informação sobre a posição das diferenças e obscurecendo quais diferenças estão emparelhadas (e não há conceito de número de linha para um SET de cordas). A utilização de -synchwindow 0 fará com que as diferenças sejam emitidas à medida que ocorrem mas impede-o de tentar re-sincronizar por isso se um ficheiro tiver uma linha extra então as comparações de linhas subsequentes podem falhar mesmo que os ficheiros sejam idênticos (até que haja uma compensação linha extra no outro arquivo realinhando assim as linhas correspondentes). No entanto, o powershell é extremamente versátil e uma comparação de arquivos útil pode ser feita utilizando essa funcionalidade, embora ao custo de uma complexidade substancial e com algumas restrições sobre o conteúdo dos arquivos. Se você precisar comparar arquivos de texto com linhas longas (> 127 caracteres) e onde as linhas correspondem principalmente a 1:
onde xx é o comprimento da linha mais longa + 9
Explicação
(gc file | % -begin { $ln=0 } -process { '{0,6}<<:{1}' -f ++$ln,$_ })
obtém o conteúdo do arquivo e acrescenta o número da linha e o indicador do arquivo (<< ou >>) a cada linha (usando o operador de string de formato) antes de passá-lo para diff.-property { $_.substring(9) }
diz ao diff para comparar cada par de objetos (strings) ignorando os primeiros 9 caracteres (que são o número da linha e o indicador do arquivo). Isso utiliza a capacidade de especificar uma propriedade calculada (o valor de um bloco de script) em vez do nome de uma propriedade.-passthru
faz com que o diff produza os diferentes objetos de entrada (que incluem o número da linha e o indicador de arquivo) em vez dos diferentes objetos comparados (que não o fazem).sort-object
em seguida, coloca todas as linhas de volta em sequência.out-string interrompe o truncamento padrão da saída para ajustar a largura da tela (conforme observado por Marc Towersap) especificando uma largura grande o suficiente para evitar o truncamento. Normalmente, esta saída seria colocada em um arquivo que é então visualizado usando um editor de rolagem (por exemplo, bloco de notas).
Observação
O formato de número de linha {0,6} fornece um número de linha de 6 caracteres justificado à direita e preenchido com espaço (para classificação). Se os arquivos tiverem mais de 999.999 linhas, basta alterar o formato para maior. Isso também requer a alteração do
$_.substring
parâmetro (3 a mais que a largura do número da linha) e o valor xx da string de saída (comprimento máximo da linha +$_.substring
parâmetro).Há também o Windiff que fornece uma interface GUI diff (ótima para uso com programas CVS/SVN baseados em GUI)
O Powershell é estranho na melhor das hipóteses e um triste substituto de diff -y. Vim aqui procurando como poderia funcionar, acabei abrindo os arquivos no notepad++. Exatamente o que eu precisava