我有两个文本文件,想使用 Windows Powershell 找出它们之间的差异。有没有类似于 Unix diff 工具的东西可用?或者还有其他我没有考虑过的方法吗?
我试过比较对象,但得到这个神秘的输出:
PS C:\> compare-object one.txt two.txt
InputObject SideIndicator
----------- -------------
two.txt =>
one.txt <=
我自己想通了。因为 Powershell 使用 .net 对象而不是文本,所以您需要使用 get-content 来公开文本文件的内容。因此,要执行我在问题中尝试执行的操作,请使用:
一种更简单的方法是编写:
或者您可以像这样使用 DOS
fc
命令(这显示了两个文件的输出,因此您必须扫描差异):fc
是 Format-Custom cmdlet 的别名,因此请务必将命令输入为fc.exe
. 请注意,许多 DOS 实用程序不处理 UTF-8 编码。您还可以生成 CMD 进程并
fc
在其中运行。这指示 PowerShell 使用引号中的参数使用“cmd”程序启动进程。在引号中,是用于运行命令并终止的 '/c' cmd 选项。在进程中由 cmd 运行的实际命令是
fc filea.txt fileb.txt
将输出重定向到文件diff.txt
。您可以在 powershell 中使用 DOS
fc.exe
。*nix 上的 diff 不是 shell 的一部分,而是一个单独的应用程序。
有什么理由不能在 PowerShell 下使用 diff.exe 吗?
您可以从 UnxUtils 软件包 ( http://unxutils.sourceforge.net/ )下载一个版本
如果您希望它的行为类似于 unix diff,那么比较对象(又名 diff 别名)是可悲的。我尝试了 diff (gc file1) (gc file2),如果一行太长,我看不到实际的 diff,更重要的是,我无法分辨 diff 所在的行号。
当我尝试添加 -passthru 时,我现在可以看到差异,但是我丢失了差异所在的文件,并且我仍然没有得到行号。
我的建议,不要使用 powershell 来查找文件中的差异。正如其他人所指出的,fc 的工作原理比 compare-object 好一点,甚至更好的是下载和使用 Mikeage 提到的 unix 模拟器等真实工具。
WinMerge是另一个很好的基于 GUI 的差异工具。
正如其他人所指出的,如果您期待 unix-y diff 输出,那么使用 powershell diff 别名会让您失望。一方面,您必须在实际读取文件时握住它的手(使用 gc / get-content)。另一方面,差异指示器位于右侧,远离内容——这是可读性的噩梦。
任何寻求理智输出的人的解决方案是
添加行
-force 参数是必需的,因为 Powershell 对于这个特定的内置别名非常宝贵。如果有人有兴趣,安装了 GnuWin32,我还在我的 powershell 配置文件中包含以下内容:
主要是因为 Powershell 不理解一起运行和键入的参数,例如“rm -Force -Recurse”比“rm -rf”要努力得多。
Powershell 有一些不错的功能,但有些事情不应该尝试为我做。
fc.exe
更适合文本比较,因为它设计为像 *nix diff 一样工作,即按顺序比较行,显示实际差异并尝试重新同步(如果不同部分具有不同的长度)。它还具有一些有用的控制选项(文本/二进制、区分大小写、行号、重新同步长度、不匹配缓冲区大小)并提供退出状态(-1 语法错误、0 个文件相同、1 个文件不同、2 个文件丢失)。作为一个(非常)旧的 DOS 实用程序,它确实有一些限制。最值得注意的是,它不会自动使用 Unicode,将 ASCII 字符的 0 MSB 视为行终止符,因此文件变成 1 字符行的序列(@kennycoc:使用 /U 选项指定 BOTH 文件都是 Unicode,WinXP 以上) 并且它还具有 128 个字符(128 字节 ASCII,compare-object 旨在确定 2 个对象在成员方面是否相同。如果对象是集合,那么它们将被视为 SETS(请参阅帮助 compare-object),即没有重复的 UNORDERED 集合。2个集合是相等的,如果它们具有相同的成员项目,而不管顺序或重复。这严重限制了它在比较文本文件的差异方面的有用性。首先,默认行为会收集差异,直到检查了整个对象(文件 = 字符串数组),从而丢失了有关差异位置的信息并模糊了哪些差异是配对的(并且没有 SET 的行号概念字符串)。使用 -synchwindow 0 将导致差异在发生时发出,但会阻止它尝试重新同步,因此如果一个文件有额外的行,那么即使文件在其他方面相同,后续行比较也会失败(直到有一个补偿另一个文件中的额外行,从而重新对齐匹配的行)。然而,powershell 非常通用,并且可以通过利用此功能来完成有用的文件比较,尽管代价是相当复杂并且对文件的内容有一些限制。如果您需要比较长(> 127 个字符)行的文本文件,并且这些行大多匹配 1:
其中 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
参数)。还有Windiff,它提供了一个 GUI 差异界面(非常适合与基于 GUI 的 CVS/SVN 程序一起使用)
Powershell 充其量是尴尬的,并且是 diff -y 的可悲替代品。我来到这里寻找它如何工作,最终在记事本++中打开文件。正是我需要的