web-dev-qa-db-fra.com

Comment différencier deux fichiers texte dans Windows Powershell?

J'ai deux fichiers texte et je veux trouver les différences entre eux en utilisant Windows Powershell. Existe-t-il quelque chose de similaire à l'outil de diff Unix disponible? Ou y a-t-il une autre voie que je n'ai pas envisagée?

J'ai essayé compare-object, mais obtenez cette sortie cryptique:

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

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

Je l'ai compris moi-même. Étant donné que Powershell fonctionne avec des objets .net plutôt qu'avec du texte, vous devez utiliser get-content pour exposer le contenu des fichiers texte. Donc, pour effectuer ce que j'essayais de faire dans la question, utilisez:

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

Une façon plus simple de le faire est d'écrire:

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

Ou vous pouvez utiliser la commande DOS fc comme ceci (cela montre la sortie des deux fichiers, vous devrez donc rechercher les différences):

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

fc est un alias pour l'applet de commande Format-Custom, veillez donc à saisir la commande en tant que fc.exe. Veuillez noter que de nombreux utilitaires DOS ne gèrent pas l'encodage UTF-8.

Vous pouvez également générer un processus CMD et y exécuter fc.

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

Cela indique à PowerShell de démarrer un processus avec le programme "cmd" en utilisant les paramètres entre guillemets. Dans les guillemets, se trouve l'option cmd '/ c' pour exécuter la commande et terminer. La commande réelle à exécuter par cmd dans le processus est fc filea.txt fileb.txt rediriger la sortie vers le fichier diff.txt.

Vous pouvez utiliser le DOS fc.exe de l'intérieur de PowerShell.

32
phord350

diff on * nix ne fait pas partie du Shell, mais une application distincte.

Y a-t-il une raison pour laquelle vous ne pouvez pas simplement utiliser diff.exe sous PowerShell?

Vous pouvez télécharger une version à partir du package UnxUtils ( http://unxutils.sourceforge.net/ )

7
Mikeage

compare-object (alias diff alias) est pathétique si vous vous attendez à ce qu'il se comporte comme un diff unix. J'ai essayé le diff (gc file1) (gc file2), et si une ligne est trop longue, je ne peux pas voir le diff réel et plus important encore, je ne peux pas dire sur quel numéro de ligne le diff est activé.

Lorsque j'essaie d'ajouter -passthru, je peux maintenant voir la différence, mais je perds dans quel fichier se trouve la différence et je n'ai toujours pas de numéro de ligne.

Mon conseil, n'utilisez pas PowerShell pour trouver des différences dans les fichiers. Comme quelqu'un d'autre l'a noté, fc fonctionne et fonctionne un peu mieux que compare-object, et encore mieux télécharge et utilise de vrais outils comme l'émulateur unix mentionné par Mikeage.

4
Marc Towersap

Comme d'autres l'ont noté, si vous vous attendiez à une sortie diff unix-y, l'utilisation de l'alias diff powershell vous laisserait tomber. D'une part, vous devez tenir la main dans la lecture des fichiers (avec gc/get-content). D'autre part, l'indicateur de différence est à droite, loin du contenu - c'est un cauchemar de lisibilité.

La solution pour tous ceux qui recherchent une sortie saine est

  1. obtenir un vrai diff (par exemple de GnuWin32)
  2. modifier% USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
  3. ajouter la ligne

    remove-item alias:diff -force
    

L'argument -force est requis car Powershell est assez précieux à propos de cet alias intégré particulier. Si quelqu'un est intéressé par l'installation de GnuWin32, j'inclus également les éléments suivants dans mon profil PowerShell:

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

Principalement parce que Powershell ne comprend pas les arguments qui sont exécutés ensemble et saisis, par exemple "rm -Force -Recurse" demande beaucoup plus d'efforts que "rm -rf".

Powershell a quelques fonctionnalités intéressantes, mais il y a des choses qu'il ne devrait tout simplement pas essayer de faire pour moi.

3
daf

WinMerge est un autre bon outil de diff basé sur GUI.

2
Andy White

fc.exe Est préférable pour la comparaison de texte car il est conçu pour fonctionner comme * nix diff, c'est-à-dire qu'il compare les lignes séquentiellement, montrant les différences réelles et essayant de resynchroniser (si les sections différentes ont des longueurs différentes). Il dispose également de quelques options de contrôle utiles (texte/binaire, respect de la casse, numéros de ligne, longueur de resynchronisation, taille du tampon de non-concordance) et fournit un état de sortie (-1 mauvaise syntaxe, 0 fichier identique, 1 fichier différent, 2 fichier manquant). Étant un (très) ancien utilitaire DOS, il a quelques limitations. Plus particulièrement, il ne fonctionne pas automatiquement avec Unicode, traitant le 0 MSB de ASCII caractères comme un terminateur de ligne de sorte que le fichier devient une séquence de 1 ligne de caractères (@kennycoc: utilisez l'option/U pour spécifier les DEUX fichiers sont Unicode, WinXP) et il a également une taille de tampon de ligne dure de 128 caractères (128 octets ASCII, 256 octets Unicode) afin que les longues lignes soient divisées et comparées séparément.

compare-object est conçu pour déterminer si 2 objets sont identiques au niveau des membres. si les objets sont des collections, ils sont traités comme des ENSEMBLES (voir l'aide compare-object), c'est-à-dire des collections NON ORDONNÉES sans doublons. 2 ensembles sont égaux s'ils ont les mêmes éléments membres indépendamment de l'ordre ou des duplications. Cela limite considérablement son utilité pour comparer les fichiers texte pour les différences. Tout d'abord, le comportement par défaut collecte les différences jusqu'à ce que l'objet entier (fichier = tableau de chaînes) ait été vérifié, perdant ainsi les informations concernant la position des différences et masquant les différences qui sont appariées (et il n'y a pas de concept de numéro de ligne pour un SET de cordes). L'utilisation de -synchwindow 0 provoquera l'émission des différences au fur et à mesure qu'elles se produiront, mais l'empêchera d'essayer de se resynchroniser, donc si un fichier a une ligne supplémentaire, les comparaisons de lignes suivantes peuvent échouer même si les fichiers sont par ailleurs identiques (jusqu'à ce qu'il y ait une compensation ligne supplémentaire dans l'autre fichier réalignant ainsi les lignes correspondantes). Cependant, powershell est extrêmement polyvalent et une comparaison de fichiers utile peut être effectuée en utilisant cette fonctionnalité, mais au prix d'une complexité substantielle et avec certaines restrictions sur le contenu des fichiers. Si vous devez comparer des fichiers texte avec de longues lignes (> 127 caractères) et où les lignes correspondent principalement à 1: 1 (quelques changements dans les lignes entre les fichiers mais pas de duplication dans un fichier comme une liste de texte des enregistrements de base de données ayant un champ clé) puis en ajoutant des informations à chaque ligne indiquant dans quel fichier il se trouve, sa position dans ce fichier et en ignorant les informations ajoutées pendant la comparaison (mais en les incluant dans la sortie), vous pouvez obtenir une sortie de type * nix diff comme suit (abréviations d'alias utilisées ):

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

où xx est la longueur de la plus longue ligne + 9

Explication

  • (gc file | % -begin { $ln=0 } -process { '{0,6}<<:{1}' -f ++$ln,$_ }) Récupère le contenu du fichier et ajoute le numéro de ligne et l'indicateur de fichier (<< ou >>) à chaque ligne (à l'aide de l'opérateur de format de chaîne) avant de le transmettre à diff.
  • -property { $_.substring(9) } indique à diff de comparer chaque paire d'objets (chaînes) en ignorant les 9 premiers caractères (qui sont le numéro de ligne et l'indicateur de fichier). Cela utilise la possibilité de spécifier une propriété calculée (la valeur d'un bloc de script) au lieu du nom d'une propriété.
  • -passthru Fait en sorte que diff affiche les différents objets d'entrée (qui incluent le numéro de ligne et l'indicateur de fichier) au lieu des objets comparés différents (qui ne le font pas).
  • sort-object Remet ensuite toutes les lignes en séquence.
    out-string arrête la troncature par défaut de la sortie pour l'adapter à la largeur de l'écran (comme l'a noté Marc Towersap) en spécifiant une largeur suffisamment grande pour éviter la troncature. Normalement, cette sortie serait placée dans un fichier qui est ensuite visualisé à l'aide d'un éditeur de défilement (par exemple le bloc-notes).

Remarque

Le format de numéro de ligne {0,6} donne un numéro de ligne de 6 caractères justifié à droite et à espace (pour le tri). Si les fichiers ont plus de 999 999 lignes, changez simplement le format pour qu'il soit plus large. Cela nécessite également de modifier le paramètre $_.substring (3 de plus que la largeur du numéro de ligne) et la valeur xx de la chaîne de sortie (longueur de ligne maximale + paramètre $_.substring).

1
codemaster bob

Il y a aussi Windiff qui fournit une interface diff GUI (idéal pour une utilisation avec des programmes CVS/SVN basés sur GUI)

1
saschabeaumont