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

#1 楼

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

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


评论


当我尝试比较两个文件时,我感到非常惊讶:一个未排序的数字数组,以及对它们进行排序后的相同数字数组。尽管文件有很大不同,但没有输出。显然,比较对象不考虑顺序。

–cgmb
2015年2月4日在6:58

@cgmb-我相信,您可以使用-SyncWindow 0来解决此问题,尽管我不确定是否是最近才引入的。不过,这并不是特别聪明。

–詹姆斯·鲁斯金(James Ruskin)
16 Jan 28 '14:49



请注意,比较大文件时,这非常慢。 DOS'fc.exe或* nix'diff是更好的选择。

– Geronimo
20年9月2日在7:28

#2 楼

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

diff (cat file1) (cat file2)


评论


Diff和cat只是PowerShell中Compare-Object和Get-Content的别名。是同一回事。

–user47078
2012-2-10的1:54



尽管这与接受的答案相同,但我更喜欢使用这种语法

– Elijah W. Gagne
18年1月12日在18:41

请注意,它根本不像* nix diff那样运行,如此处的其他答案所述。并且当我使用更复杂的表达式代替cat时,我得到了错误的输出,因此如果您来自* nix,我将与其他建议一起加入以避免在PowerShell中执行此操作。

– Nickolay
19-09-3在12:43

#3 楼

或者,您可以像这样使用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。您可以在powershell中使用DOS fc.exe

评论


+1用于显示DOS ^ _ ^

–杰夫B
13年4月17日在15:21

“ fc”不适用于我,并且我没有意识到我必须将其指定为“ fc.exe”以区别于Format-Custom。正是我想要的。谢谢。

– Xonatron
17年9月17日在13:44

也许我是一个完整的非利士人,但这对我来说似乎更有用。它很好地解决了我的问题。

– AJ。
18年7月2日在10:03



唯一的问题是它破坏了Unicode。

– iCodeSometime
18/12/18在11:57

#4 楼

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

有什么理由不能只在PowerShell下使用diff.exe吗?

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

评论


由于现在包括PowerShell,因此无需下载和安装任何内容。

–括号
2012年7月31日下午16:34

我刚结束使用git diff,因为我已经安装了它。 fc.exe和Compare-Object均未产生我期望的输出。

–拉济尔
18年8月28日在11:40

#5 楼

如果您希望compare-object(也称为diff别名)表现得像unix diff,则很可悲。我尝试了diff(gc file1)(gc file2),如果一行太长,我看不到实际的diff,更重要的是,我无法确定diff在哪一行上。

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

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

评论


由于默认情况下-SyncWindow为maxint,因此它似乎也进行了设置比较(即忽略顺序)。将其设置为0也不会使它像diff一样工作。当我通过管道(... | select-object ...)作为输入时,它只是打印废话,所以我放弃了。

– Nickolay
19年9月3日,12:54

Compare-Object不是可悲的,它旨在“比较两组对象”(请参阅​​Get-Help Compare-Object |更多信息)。不是您要尝试做的。关于截止输出,PowerShell命令返回的对象可以被脚本化/管道化而无需解析。如果您对文本输出感兴趣,请签出Format- * cmdlet或通过管道发送到您喜欢的编辑器,然后获取所需的行号。

– Vimes
20年5月8日在22:47

#6 楼

正如其他人指出的那样,如果您期望使用unix-y diff输出,那么使用powershell diff别名会让您很难过。一方面,您必须握住它来实际读取文件(使用gc / get-content)。另外,差异指示器在右边,远离内容-这是可读性的噩梦。 />获取真正的差异(例如来自GnuWin32)
编辑%USERPROFILE%\ Documents \ WindowsPowerShell \ Microsoft.PowerShell_profile.ps1

添加行

remove-item alias:diff -force



-force参数是必需的,因为Powershell对于此特定的内置别名非常宝贵。如果有人感兴趣,安装了GnuWin32,我还将在我的powershell配置文件中添加以下内容: ,例如,“ rm -Force -Recurse”比“ rm -rf”要费很多力气。 。

#7 楼

WinMerge是另一个基于GUI的优秀差异工具。

评论


我过去是这样做的,这是一个手动过程,我想用一个小脚本替换。

–括号
2012年7月31日下午16:35

#8 楼

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

评论


但是问题特别是:如何在Windows Powershell中区分两个文本文件

– P-L
20-3-24在20:10



#9 楼

fc.exe更适合于文本比较,因为它的设计原理类似于* nix diff,即顺序比较行,显示实际差异并尝试重新同步(如果不同部分的长度不同)。它还具有一些有用的控制选项(文本/二进制,区分大小写,行号,重新同步长度,不匹配的缓冲区大小),并提供退出状态(-1错误的语法,0个相同的文件,1个不同的文件,2个丢失的文件)。作为(非常)旧的DOS实用程序,它确实有一些限制。最值得注意的是,它不能自动与Unicode一起使用,将0个ASCII字符的MSB作为行终止符,因此文件变成1个字符行的序列(@kennycoc:使用/ U选项指定两个文件均为Unicode,从WinXP开始),并且硬线缓冲区大小为128个字符(128个字节的ASCII,256个Unicode的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所述)避免被截断。通常,将此输出放入一个文件中,然后使用滚动编辑器(例如记事本)进行查看。

Note

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

评论


Shunz先生给出的长期解决方案经过精心设计,可提供良好的可读性输出。但是,它有一个固有的问题:它不返回行的移动(例如几条交换的行)。例如,如果文件1包含行1、2和3,文件2包含行1、3和2,则不会报告差异。

–安德烈·特里谢(Andre Trichet)
20 Mar 5 '20 at 17:35