it-swarm.cn

如何在Windows Powershell中区分两个文本文件?

我有两个文本文件,想要使用Windows Powershell查找它们之间的差异。是否有类似于Unix diff工具的工具?还是我还没有考虑过其他方法?

我尝试了compare-object,但是得到了这个神秘的输出:

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

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

我自己想通了。由于Powershell使用的是.net对象而不是文本,因此您需要使用get-content公开文本文件的内容。因此,要执行我在问题中试图做的事情,请使用:

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

一种更简单的方法是编写:

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

或者,您可以像这样使用DOS fc命令(这显示了两个文件的输出,因此您必须扫描差异):

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

fc是Format-Custom cmdlet的别名,因此请确保输入命令为fc.exe。请注意,许多DOS实用程序不处理UTF-8编码。

您还可以生成CMD进程并在其中运行fc

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

这指示PowerShell使用引号中的参数使用“ cmd”程序启动进程。用引号引起来的是'/ c'cmd选项,用于运行命令并终止。在此过程中,由cmd运行的实际命令是fc filea.txt fileb.txt将输出重定向到文件diff.txt

您可以使用DOS fc.exe从powershell内部。

32
phord350

* nix上的diff不是Shell的一部分,而是一个单独的应用程序。

有什么原因不能只在PowerShell下使用diff.exe?

您可以从UnxUtils程序包( http://unxutils.sourceforge.net/ )下载版本

7
Mikeage

如果您希望比较对象(例如diff别名)表现得像Unix diff一样,那是可悲的。我尝试了diff(gc file1)(gc file2),如果一行太长,我看不到实际的diff,更重要的是,我无法确定diff所在的行号。

当我尝试添加-passthru时,现在可以看到区别,但是我丢失了区别所在的文件,但仍然没有获得行号。

我的建议是,不要使用powershell查找文件中的差异。正如其他人指出的那样,fc可以工作,并且比比较对象要好一些,甚至更好的是下载和使用Mikeage提到的诸如unix模拟器的真实工具。

4
Marc Towersap

正如其他人指出的那样,如果您期望使用unix-y diff输出,那么使用powershell diff别名会让您很难过。一方面,您必须握住它的手才能实际读取文件(使用gc/get-content)。另一方面,差异指示器位于右侧,距离内容很远-这是可读性的噩梦。

对于任何寻求合理输出的解决方案是

  1. 得到一个真正的差异(例如从GnuWin32)
  2. 编辑%USERPROFILE%\ Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
  3. 添加线

    remove-item alias:diff -force
    

-force参数是必需的,因为Powershell对于此特定的内置别名非常宝贵。如果有人感兴趣,安装了GnuWin32,我还将在powershell配置文件中添加以下内容:

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

主要是因为Powershell无法理解同时运行并键入的参数,例如,“ rm -Force -Recurse”比“ rm -rf”需要更多的精力。

Powershell具有一些不错的功能,但有些事情它不应该为我做。

3
daf

WinMerge 是另一个很好的基于GUI的差异工具。

2
Andy White

_fc.exe_更适合文本比较,因为它的设计类似于* nix diff,即顺序比较行,显示实际差异并尝试重新同步(如果不同部分的长度不同)。它还具有一些有用的控制选项(文本/二进制,区分大小写,行号,重新同步长度,不匹配的缓冲区大小),并提供退出状态(-1错误的语法,0个相同的文件,1个不同的文件,2个丢失的文件)。作为(非常)旧的DOS实用程序,它确实有一些限制。最值得注意的是,它不能自动使用Unicode,将ASCII)字符的0 MSB视为行终止符,因此文件变成1个字符行的序列(@kennycoc:使用/ U选项用来指定两个文件都是Unicode,从WinXP开始),并且它的硬线缓冲区大小为128个字符(128字节ASCII,256字节Unicode),因此长行被分开并分别比较。

compare-object用于确定2个对象在成员方面是否相同。如果对象是集合,则将它们视为SETS(请参阅帮助比较对象),即无重复的UNORDERED集合。如果成员项相同,则无论顺序或重复项如何,两组都相等。这严重限制了它在比较文本文件是否有差异方面的有用性。首先,默认行为会收集差异,直到检查了整个对象(文件=字符串数组),从而丢失了有关差异位置的信息,并模糊了配对的差异(并且SET中没有行号的概念)的字符串)。使用-synchwindow 0会导致差异出现时发出,但会阻止差异尝试重新同步,因此,如果一个文件有多余的行,那么即使文件是相同的,后续的行比较也可能失败(除非有补偿)其他文件中的多余行,从而重新对齐匹配的行)。但是,powershell具有极强的通用性,并且可以通过利用此功能来完成有用的文件比较,尽管这样做的代价是相当复杂,并且对文件内容有一些限制。如果您需要比较具有长行(> 127个字符)且文本行大部分匹配1:1的文本文件(文件之间的行有些变化,但文件内没有重复项,例如具有键字段的数据库记录的文本列表)然后通过向每行添加信息以指示该文件在哪个文件中,文件在该文件中的位置,然后在比较期间忽略添加的信息(但将其包括在输出中),可以得到一个* nix diff,如下所示(使用别名) ):

_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
_

其中xx是最长线的长度+ 9

说明

  • _(gc file | % -begin { $ln=0 } -process { '{0,6}<<:{1}' -f ++$ln,$_ })_获取文件的内容,并将行号和文件指示符(<<或>>)添加到每一行(使用格式字符串运算符),然后再将其传递给diff。
  • -property { $_.substring(9) }告诉diff比较忽略了前9个字符(即行号和文件指示符)的每对对象(字符串)。这利用了指定计算所得的属性(脚本块的值)而不是属性名称的能力。
  • _-passthru_导致diff输出不同的输入对象(包括行号和文件指示符),而不是不同的比较对象(不包括)。
  • _sort-object_然后将所有行放回序列中。
    out-string通过指定足以避免截断的宽度来停止输出的默认截断以适合屏幕宽度(如Marc Towersap所述)。通常,此输出将放入文件中,然后使用滚动编辑器(例如记事本)进行查看。

注意

行号格式{0,6}给出一个右对齐的空格填充6个字符的行号(用于排序)。如果文件的行数超过999,999,则只需将格式更改为更宽即可。这还需要更改_$_.substring_参数(比行号宽度多3)和字符串xx值(最大行长+ _$_.substring_参数)。

1
codemaster bob

还有 Windiff 提供GUI差异接口(非常适合与基于GUI的CVS/SVN程序一起使用)

1
saschabeaumont