Назад | Перейти на главную страницу

Как отличить два текстовых файла в Windows Powershell?

У меня есть два текстовых файла, и я хочу найти различия между ними с помощью Windows Powershell. Есть ли что-то похожее на инструмент Unix diff? Или есть другой способ, который я не рассматривал?

Я пробовал сравнивать объект, но получаю такой загадочный результат:

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

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

Разобрался сам. Поскольку Powershell работает с объектами .net, а не с текстом, вам нужно использовать get-content, чтобы раскрыть содержимое текстовых файлов. Итак, чтобы выполнить то, что я пытался сделать в вопросе, используйте:

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

Более простой способ сделать это - написать:

diff (cat file1) (cat file2)

Или вы можете использовать DOS fc такую ​​команду (это показывает вывод обоих файлов, поэтому вам придется сканировать на предмет различий):

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

fc является псевдонимом для командлета Format-Custom, поэтому обязательно введите команду как fc.exe. Обратите внимание, что многие утилиты DOS не поддерживают кодировку UTF-8.

Вы также можете создать процесс CMD и запустить fc внутри.

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

Это указывает PowerShell на запуск процесса с программой cmd, используя параметры в кавычках. В кавычках указан параметр cmd '/ c' для запуска и завершения команды. Фактическая команда для запуска cmd в процессе: fc filea.txt fileb.txt перенаправление вывода в файл diff.txt.

Вы можете использовать DOS fc.exe изнутри PowerShell.

diff on * nix - это не часть оболочки, а отдельное приложение.

Есть ли причина, по которой вы не можете просто использовать diff.exe в PowerShell?

Вы можете скачать версию из пакета UnxUtils (http://unxutils.sourceforge.net/)

compare-object (он же псевдоним diff) выглядит жалко, если вы ожидаете, что он будет вести себя как-то вроде unix diff. Я попробовал diff (gc file1) (gc file2), и если строка слишком длинная, я не могу увидеть фактическую разницу и, что более важно, я не могу сказать, на каком номере строки находится разница.

Когда я пытаюсь добавить -passthru, теперь я вижу разницу, но теряю, в каком файле есть разница, и все еще не получаю номер строки.

Мой совет: не используйте PowerShell для поиска различий в файлах. Как заметил кто-то другой, fc работает и работает немного лучше, чем compare-object, и даже лучше загружать и использовать настоящие инструменты, такие как эмулятор unix, о котором упоминал Майкидж.

Как отмечали другие, если вы ожидали вывода 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 есть несколько хороших функций, но есть некоторые вещи, которые он не должен делать за меня.

WinMerge - еще один хороший инструмент сравнения с графическим интерфейсом.

Есть также Виндифф который предоставляет графический интерфейс diff (отлично подходит для использования с программами CVS / SVN на основе графического интерфейса)

fc.exe лучше подходит для сравнения текста, так как он разработан для работы как * nix diff, то есть сравнивает строки последовательно, показывая фактические различия и пытается повторно синхронизировать (если разные разделы имеют разную длину). Он также имеет некоторые полезные параметры управления (текст / двоичный код, чувствительность к регистру, номера строк, длина повторной синхронизации, размер буфера несоответствия) и предоставляет статус выхода (-1 неверный синтаксис, 0 файлов одинаково, 1 файл отличается, 2 файла отсутствуют). Будучи (очень) старой служебной программой DOS, она имеет несколько ограничений. В частности, он не работает автоматически с Unicode, обрабатывая 0 MSB символов ASCII как признак конца строки, поэтому файл становится последовательностью из 1 символьных строк (@kennycoc: используйте параметр / U, чтобы указать, что ОБА файлы являются Unicode, WinXP и далее ), и он также имеет размер жесткого буфера строки 128 символов (128 байтов ASCII, 256 байтов Unicode), поэтому длинные строки разделяются и сравниваются отдельно.

compare-object предназначен для определения идентичности двух объектов по элементам. если объекты являются коллекциями, они обрабатываются как НАБОРЫ (см. help compare-object), то есть НЕПОРЯДОЧЕННЫЕ коллекции без дубликатов. 2 набора равны, если они содержат одинаковые элементы, независимо от порядка или дублирования. Это сильно ограничивает его полезность для сравнения текстовых файлов на предмет различий. Во-первых, поведение по умолчанию собирает различия до тех пор, пока не будет проверен весь объект (файл = массив строк), что приведет к потере информации о положении различий и сокрытию того, какие различия объединены в пары (и нет понятия номера строки для SET струн). Использование -synchwindow 0 приведет к тому, что различия будут выдаваться по мере их появления, но не даст ему попытаться повторно синхронизировать, поэтому, если в одном файле есть дополнительная строка, последующие сравнения строк могут завершиться неудачно, даже если файлы в остальном идентичны (до тех пор, пока не будет компенсирующего дополнительная строка в другом файле, тем самым выравнивая совпадающие строки). Однако PowerShell чрезвычайно универсален, и с помощью этой функции можно выполнить полезное сравнение файлов, хотя и за счет существенной сложности и с некоторыми ограничениями на содержимое файлов. Если вам нужно сравнить текстовые файлы с длинными (> 127 символов) строками и где строки в основном соответствуют 1: 1 (некоторые изменения в строках между файлами, но без дублирования внутри файла, например текстовый список записей базы данных, имеющих ключевое поле) затем, добавляя информацию в каждую строку, указывающую, в каком файле он находится, его положение в этом файле, а затем игнорируя добавленную информацию во время сравнения (но включая ее в вывод), вы можете получить вывод, похожий на * nix, как показано ниже (используются аббревиатуры псевдонимов ):

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 останавливает усечение вывода по умолчанию, чтобы соответствовать ширине экрана (как отметил Марк Тауэрсап), задав ширину, достаточно большую, чтобы избежать усечения. Обычно этот вывод помещается в файл, который затем просматривается с помощью редактора с прокруткой (например, блокнота).

Заметка

Формат номера строки {0,6} дает выровненный по правому краю шестизначный номер строки, заполненный пробелами (для сортировки). Если файлы содержат более 999 999 строк, просто измените формат на более широкий. Это также требует изменения $_.substring параметр (на 3 больше, чем ширина номера строки) и значение xx вне строки (максимальная длина строки + $_.substring параметр).