Come diffondo due file di testo in Windows Powershell?


96

Ho due file di testo e voglio trovare le differenze tra loro usando Windows Powershell. È disponibile qualcosa di simile allo strumento diff Unix? O c'è un altro modo che non ho preso in considerazione?

Ho provato a confrontare-oggetto, ma ottengo questo output criptico:

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

InputObject                                                 SideIndicator
-----------                                                 -------------
two.txt                                                     =>
one.txt                                                     <=

Risposte:


101

Ho capito da solo. Poiché Powershell funziona con oggetti .net anziché con il testo, è necessario utilizzare get-content per esporre il contenuto dei file di testo. Quindi, per eseguire ciò che stavo cercando di fare nella domanda, utilizzare:

compare-object (get-content one.txt) (get-content two.txt)

1
Sono stato molto sorpreso quando ho provato a confrontare due file: una matrice di numeri non ordinata e la stessa matrice di numeri dopo averli ordinati. Non c'è output nonostante i file siano molto diversi. Apparentemente, compare-object non considera l'ordine.
CGM,

1
@cgmb - Puoi usarlo -SyncWindow 0per risolvere questo, credo, anche se non sono sicuro che sia stato introdotto solo di recente. Non è particolarmente intelligente, però.
James Ruskin,

32

Un modo più semplice di farlo è scrivere:

diff (cat file1) (cat file2)

16
Diff e cat sono solo alias per Compare-Object e Get-Content in PowerShell. E 'la stessa cosa.
Shawn Melton,

4
nonostante sia la stessa risposta accettata, mi piace usare di più questa sintassi
Elijah W. Gagne

Nota che non si comporta affatto come * nix diff, come notano altre risposte qui. E quando ho usato un'espressione più complessa al posto di catho ottenuto un output errato, quindi mi unirò agli altri nella raccomandazione per evitare di farlo in PowerShell se venite da * nix.
Nickolay,

29

Oppure potresti usare il fccomando DOS in questo modo (Questo mostra l'output di entrambi i file, quindi dovrai cercare le differenze):

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

fcè un alias per il cmdlet Format-Custom, quindi assicurarsi di immettere il comando asfc.exe . Si noti che molte utility DOS non gestiscono la codifica UTF-8.

Puoi anche generare un processo CMD ed eseguirlo al fcsuo interno.

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

Questo indica a PowerShell di avviare un processo con il programma 'cmd' usando i parametri tra virgolette. Tra virgolette, c'è l'opzione cmd '/ c' per eseguire il comando e terminare. Il comando effettivo eseguito da cmd nel processo sta fc filea.txt fileb.txtreindirizzando l'output sul file diff.txt.

È possibile utilizzare il DOS fc.exeda PowerShell.


2
+1 per far uscire il DOS ^ _ ^
Jeff Bridgman,

1
"fc" non funzionava per me e non mi rendevo conto che dovevo specificarlo come "fc.exe" per differenziarlo da Format-Custom. Esattamente quello che stavo cercando. Grazie.
Xonatron,

Forse sono un completo filisteo, ma questo mi sembra molto più utilizzabile. Ha risolto il mio problema molto bene.
AJ.

L'unico problema è odia Unicode.
iCodeSometime

7

diff su * nix non fa parte della shell, ma un'applicazione separata.

C'è qualche motivo per cui non puoi semplicemente usare diff.exe in PowerShell?

Puoi scaricare una versione dal pacchetto UnxUtils ( http://unxutils.sourceforge.net/ )


10
Poiché PowerShell è ora incluso, nulla da scaricare e installare.
Bratch

Ho appena finito di usare git diff, perché l'avevo già installato. Né fc.exeCompare-Objectprodotta l'uscita che mi aspettavo.
Raziel,

4

compare-object (alias diff alias) è patetico se ti aspetti che si comporti come qualcosa di simile a unix diff. Ho provato il diff (gc file1) (gc file2), e se una linea è troppo lunga, non riesco a vedere il diff reale e, cosa più importante, non posso dire su quale numero di riga si trova il diff.

Quando provo ad aggiungere -passthru, ora posso vedere la differenza, ma perdo il file in cui si trova la differenza e ancora non ottengo un numero di riga.

Il mio consiglio, non usare PowerShell per trovare differenze nei file. Come ha notato qualcun altro, fc funziona e funziona un po 'meglio di compare-object, e ancora meglio sta scaricando e usando strumenti reali come l'emulatore unix menzionato da Mikeage.


Sembra anche fare un confronto impostato (cioè ignorare l'ordine) come -SyncWindowmaxint di default. Impostarlo su 0 non lo fa funzionare come diffuno dei due ... E quando ho passato una pipe (... | select-object ...)come input, ha semplicemente stampato delle sciocchezze, quindi ho rinunciato.
Nickolay,

3

Come altri hanno notato, se ti aspettavi un output diff unix-y, l'uso dell'alias diff di PowerShell ti deluderebbe duramente. Per prima cosa, devi tenere la mano nella lettura dei file (con gc / get-content). Per un altro, l'indicatore di differenza è sulla destra, lontano dal contenuto: è un incubo di leggibilità.

La soluzione per chiunque cerchi un risultato sano è

  1. ottenere un vero diff (ad esempio da GnuWin32)
  2. modifica% USERPROFILE% \ Documents \ WindowsPowerShell \ Microsoft.PowerShell_profile.ps1
  3. aggiungi la linea

    remove-item alias:diff -force

L'argomento -force è richiesto perché Powershell è piuttosto prezioso su questo particolare alias integrato. Se qualcuno è interessato, avendo installato GnuWin32, includo anche quanto segue nel mio profilo PowerShell:

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

Soprattutto perché Powershell non capisce gli argomenti che vengono eseguiti insieme e digitando, ad esempio "rm -Force -Recurse" è uno sforzo molto maggiore di "rm -rf".

Powershell ha alcune caratteristiche interessanti, ma ci sono alcune cose che non dovrebbe semplicemente provare a fare per me.


2

WinMerge è un altro buon strumento diff basato sulla GUI.


1
È così che ho fatto in passato, che è un processo manuale, che volevo sostituire con un piccolo script.
Bratch

1

C'è anche Windiff che fornisce un'interfaccia diff GUI (ottima per l'uso con programmi CVS / SVN basati su GUI)


1

fc.exeè migliore per il confronto del testo poiché progettato per funzionare come * nix diff, ovvero confronta le linee in sequenza, mostrando le differenze effettive e cercando di risincronizzare (se le diverse sezioni hanno lunghezze diverse). Ha anche alcune utili opzioni di controllo (testo / binario, distinzione tra maiuscole e minuscole, numeri di riga, lunghezza della risincronizzazione, dimensioni del buffer di mancata corrispondenza) e fornisce lo stato di uscita (-1 sintassi errata, 0 file uguali, 1 file diverso, 2 file mancanti). Trattandosi di una (molto) vecchia utility DOS, presenta alcune limitazioni. In particolare, non funziona automaticamente con Unicode, trattando lo 0 MSB di caratteri ASCII come un terminatore di riga, quindi il file diventa una sequenza di 1 righe di caratteri (@kennycoc: utilizzare l'opzione / U per specificare ENTRAMBE i file sono Unicode, WinXP in poi ) e ha anche una dimensione del buffer di linea dura di 128 caratteri (128 byte ASCII,

compare-object è progettato per determinare se 2 oggetti sono identici per quanto riguarda i membri. se gli oggetti sono raccolte, vengono trattati come SET (consultare la guida di confronto-oggetto), ovvero raccolte NON ORDINATE senza duplicati. 2 set sono uguali se hanno gli stessi elementi membro indipendentemente dall'ordine o dalle duplicazioni. Ciò limita fortemente la sua utilità per il confronto dei file di testo per le differenze. In primo luogo, il comportamento predefinito raccoglie le differenze fino a quando l'intero oggetto (file = array di stringhe) non è stato verificato, perdendo così le informazioni sulla posizione delle differenze e oscurando quali differenze sono accoppiate (e non esiste un concetto di numero di riga per un SET di stringhe). L'uso di -synchwindow 0 farà sì che le differenze vengano emesse man mano che si verificano, ma ne impedisce il tentativo di risincronizzazione, quindi se un file ha una linea in più, i successivi confronti di linea possono fallire anche se i file sono altrimenti identici (fino a quando non c'è un compenso linea aggiuntiva nell'altro file riallineare le linee corrispondenti). Tuttavia, PowerShell è estremamente versatile e un utile confronto dei file può essere fatto utilizzando questa funzionalità, anche se a costo di una sostanziale complessità e con alcune restrizioni sul contenuto dei file. Se devi confrontare i file di testo con linee lunghe (> 127 caratteri) e dove le linee corrispondono principalmente a 1:

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

dove xx è la lunghezza della linea più lunga + 9

Spiegazione

  • (gc file | % -begin { $ln=0 } -process { '{0,6}<<:{1}' -f ++$ln,$_ }) ottiene il contenuto del file e antepone il numero di riga e l'indicatore del file (<< o >>) a ciascuna riga (utilizzando l'operatore stringa di formato) prima di passarlo a diff.
  • -property { $_.substring(9) }dice a diff di confrontare ogni coppia di oggetti (stringhe) ignorando i primi 9 caratteri (che sono il numero di riga e l'indicatore del file). Questo utilizza la possibilità di specificare una proprietà calcolata (il valore di un blocco di script) anziché il nome di una proprietà.
  • -passthru fa sì che diff generi in output i diversi oggetti di input (che includono il numero di riga e l'indicatore del file) invece dei diversi oggetti confrontati (che non lo fanno).
  • sort-objectquindi riporta tutte le linee in sequenza.
    out-string arresta il troncamento predefinito dell'output per adattarlo alla larghezza dello schermo (come notato da Marc Towersap) specificando una larghezza abbastanza grande da evitare il troncamento. Normalmente, questo output verrebbe inserito in un file che verrà quindi visualizzato usando un editor a scorrimento (ad es. Blocco note).

Nota

Il formato del numero di riga {0,6} fornisce un numero di riga di 6 caratteri con spazio giustificato a destra (per l'ordinamento). Se i file hanno più di 999.999 righe, cambia semplicemente il formato in modo che sia più ampio. Ciò richiede anche la modifica del $_.substringparametro (3 in più rispetto alla larghezza del numero di riga) e il valore xx della stringa esterna (lunghezza massima della riga + $_.substringparametro).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.