it-swarm-pt.tech

Como diferencio dois arquivos de texto no Windows Powershell?

Eu tenho dois arquivos de texto e quero encontrar as diferenças entre eles usando o Windows Powershell. Existe algo semelhante à ferramenta diff Unix disponível? Ou existe outra maneira de não considerar?

Eu tentei comparar objeto, mas obtenha esta saída enigmática:

PS C:\> compare-object one.txt two.txt

InputObject                                                 SideIndicator
-----------                                                 -------------
two.txt                                                     =>
one.txt                                                     <=
104
Brian Willis

Eu mesmo descobri. Como o Powershell trabalha 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:

compare-object (get-content one.txt) (get-content two.txt)
110
Brian Willis

Uma maneira mais simples de fazer isso é escrever:

diff (cat file1) (cat file2)
34
Alex Y.

Ou você pode usar o comando DOS fc da seguinte maneira (Isso mostra a saída dos dois arquivos para que você tenha que procurar as diferenças):

fc.exe filea.txt fileb.txt > diff.txt

fc é um alias para o cmdlet Format-Custom, certifique-se de inserir o comando como fc.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 executar fc dentro dele.

start cmd "/c  ""fc filea.txt fileb.txt >diff.txt"""

Isso instrui o PowerShell a iniciar um processo com o programa 'cmd' usando os parâmetros entre aspas. Nas aspas, é a opção '/ c' cmd para executar o comando e finalizar. O comando real a ser executado pelo cmd no processo é fc filea.txt fileb.txt redirecionando a saída para o arquivo diff.txt.

Você pode usar o DOS fc.exe de dentro do PowerShell.

32
phord350

o diff on * nix não faz parte do Shell, mas um aplicativo separado.

Existe algum motivo para você não poder usar o diff.exe no PowerShell?

Você pode baixar uma versão do pacote UnxUtils ( http://unxutils.sourceforge.net/ )

7
Mikeage

o compare-object (também conhecido como diff) é patético se você espera que se comporte como um diff unix. Eu tentei o diff (gc file1) (gc file2) e, se uma linha é muito longa, não consigo ver o diff real e, mais importante, não sei dizer em qual número de linha o diff está.

Quando tento adicionar -passthru, agora vejo a diferença, mas perco em qual arquivo está a diferença e ainda não recebo o número da linha.

Meu conselho, não use o PowerShell para encontrar diferenças nos arquivos. Como outra pessoa notou, o fc funciona e funciona um pouco melhor do que o objeto comparar, e ainda melhor é baixar e usar ferramentas reais, como o emulador unix que o Mikeage mencionou.

4
Marc Towersap

Como outros observaram, se você estava esperando uma saída diff unix-y, o uso do apelido diff do powershell o deixaria muito decepcionado. Por um lado, você tem que segurar a mão para realmente ler os 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ã é

  1. obter um diff real (por exemplo, do GnuWin32)
  2. editar% USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
  3. adicione a linha

    remove-item alias:diff -force
    

O argumento -force é necessário porque o Powershell é bastante precioso sobre esse alias embutido específico. Se alguém estiver interessado, com o GnuWin32 instalado, também incluo o seguinte no meu perfil do PowerShell:

remove-item alias:rm
remove-item alias:mv
remove-item alias:cp

Principalmente porque o Powershell não entende argumentos que são executados juntos e digitados, por exemplo "rm -Force -Recurse" é muito mais esforço do que "rm -rf".

O Powershell possui alguns recursos interessantes, mas há algumas coisas que ele simplesmente não deve tentar fazer por mim.

3
daf

WinMerge é outra boa ferramenta diff baseada em GUI.

2
Andy White

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 seções diferentes tiverem comprimentos diferentes). Ele também possui algumas opções de controle úteis (texto/binário, distinção entre maiúsculas e minúsculas, números de linhas, comprimento de ressincronização, tamanho do buffer incompatível) e fornece status de saída (-1 sintaxe incorreta, 0 arquivos iguais, 1 arquivo diferente, 1 arquivo diferente e 2 arquivos ausentes). Sendo um utilitário (muito) antigo do DOS, ele tem algumas limitações. Mais notavelmente, ele não funciona automaticamente com Unicode, tratando o MSB 0 de ASCII como um terminador de linha, para que o arquivo se torne uma sequência de 1 linha de caracteres (@kennycoc: use a opção/U para especificar AMBOS os arquivos são Unicode, WinXP em diante) e também possui um tamanho de buffer de linha dura de 128 caracteres (128 bytes ASCII, 256 bytes Unicode) para que as longas linhas sejam divididas e comparadas separadamente.

compare-object foi desenvolvido para determinar se 2 objetos são idênticos em termos de membros. se os objetos forem coleções, eles serão tratados como SETS (consulte a ajuda para comparar objetos), ou seja, coleções não ordenadas sem duplicatas. 2 conjuntos são iguais se tiverem os mesmos itens de membro, independentemente de pedido ou duplicação. Isso limita severamente sua utilidade na comparação de arquivos de texto quanto a diferenças. Primeiro, o comportamento padrão coleta as diferenças até que todo o objeto (file = array of strings) tenha sido verificado, perdendo as informações 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). O uso de -synchwindow 0 fará com que as diferenças sejam emitidas à medida que ocorrerem, mas impedirá a tentativa de sincronizar novamente. Se um arquivo tiver uma linha extra, as comparações de linha subsequentes poderão falhar, mesmo que os arquivos sejam idênticos (até que exista uma compensação linha extra no outro arquivo realinhando as linhas correspondentes). No entanto, o PowerShell é extremamente versátil e uma comparação útil de arquivos 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 em que as linhas correspondam principalmente a 1: 1 (algumas alterações nas linhas entre arquivos, mas não há duplicatas em um arquivo, como uma listagem de texto dos registros do banco de dados com um campo-chave) adicionando informações a cada linha indicando em qual arquivo ele está, sua posição nesse arquivo e ignorando as informações adicionadas durante a comparação (mas incluindo-as na saída), você pode obter uma saída * nix diff como a seguir (alias abreviações usadas ):

diff (gc file1 | % -begin { $ln1=0 } -process { '{0,6}<<:{1}' -f ++$ln1,$_ }) (gc file2 | % -begin { $ln2=0 } -process { '{0,6}>>:{1}' -f ++$ln2,$_ }) -property { $_.substring(9) } -passthru | sort | out-string -width xx

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 precede o número da linha e o indicador de arquivo (<< ou >>) para cada linha (usando o operador de cadeia de formato) antes de passar para diff.
  • -property { $_.substring(9) } informa ao diff para comparar cada par de objetos (strings) ignorando os 9 primeiros caracteres (que são o número da linha e o indicador de 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 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 Coloca todas as linhas de volta em seqüência.
    A string interrompe o truncamento padrão da saída para se ajustar à largura da tela (conforme observado por Marc Towersap) especificando uma largura grande o suficiente para evitar o truncamento. Normalmente, essa saída é colocada em um arquivo que é visualizado usando um editor de rolagem (por exemplo, o bloco de notas).

Nota

O formato do número da 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 ser maior. Isso também requer a alteração do parâmetro $_.substring (3 a mais que a largura do número da linha) e do valor da cadeia de caracteres xx (comprimento máximo da linha + parâmetro $_.substring).

1
codemaster bob

Há também Windiff , que fornece uma interface de interface gráfica do usuário (ótima para uso com programas CVS/SVN baseados em GUI)

1
saschabeaumont