Як я відрізняю два текстові файли в Windows Powershell?


96

У мене є два текстові файли і хочу знайти відмінності між ними за допомогою Windows Powershell. Чи є щось подібне до інструменту Unix diff? Або є інший спосіб, який я не розглядав?

Я спробував порівняти-об'єкт, але отримаю це криптовалюта:

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

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

Відповіді:


101

Я зрозумів це сам. Оскільки Powershell працює з .net-об’єктами, а не текстом, вам потрібно використовувати get-content для викриття вмісту текстових файлів. Отже, щоб виконати те, що я намагався зробити у питанні, використовуйте:

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

1
Я дуже здивувався, коли спробував порівняти два файли: несортований масив чисел і той самий масив чисел після їх сортування. Немає результатів, незважаючи на те, що файли дуже різні. Мабуть, порівнювати-об'єкт не враховує порядок.
cgmb

1
@cgmb - Ви можете -SyncWindow 0це виправити, я вважаю, хоча я не впевнений, якщо він був представлений лише нещодавно. Однак це не особливо розумно.
Джеймс Рускін

32

Простіший спосіб зробити це - написати:

diff (cat file1) (cat file2)

15
Diff і cat - це лише псевдоніми для Порівняння-об’єкта та отримання вмісту в PowerShell. Це те саме.
Шон Мелтон

4
незважаючи на те, що це те саме, що і прийнята відповідь, мені більше подобається використовувати цей синтаксис
Ілля В. Гагне

Зауважте, що він взагалі не поводиться як * nix diff, як зазначають інші відповіді. І коли я використав більш складний вираз замість цього, catя отримав неправильний вихід, тому я приєднаюся до інших у рекомендації уникати цього робити в PowerShell, якщо ви походите з * nix.
Миколай

29

Або ви можете використовувати команду 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', використовуючи параметри в лапки. У лапках є опція '/ c' cmd для запуску команди та завершення. Фактична команда, яку слід виконати cmd у процесі, - це fc filea.txt fileb.txtперенаправлення виводу у файл diff.txt.

Ви можете використовувати DOS fc.exeзсередини.


2
+1 за те, щоб вивести DOS ^ _ ^
Джефф Брідгман

1
"fc" не працював для мене, і я не розумів, що мені потрібно було вказати його як "fc.exe", щоб відмежувати його від формату-користувальницького. Саме те, що я шукав. Дякую.
Xonatron

Можливо, я повний міщанин, але це здається мені набагато кориснішим. Це дуже добре вирішило мою проблему.
AJ.

Єдина проблема - це HATES unicode.
iCodeSometime

7

diff on * nix - не частина оболонки, а окреме застосування.

Чи є якась причина, що ви не можете просто використовувати diff.exe під PowerShell?

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


10
Оскільки PowerShell включений зараз, не потрібно нічого завантажувати та встановлювати.
Братч

Я просто закінчила використання git diff, тому що я вже встановила його. Ні я fc.exeне Compare-Objectдав очікуваного результату.
Разіель

4

Порівняння-об'єкт (він же інакший псевдонім) є жалюгідним, якщо ви очікуєте, що він буде вести щось на зразок unix diff. Я спробував diff (gc file1) (gc file2), і якщо рядок занадто довгий, я не можу побачити фактичний diff і, що ще важливіше, я не можу сказати, на якому номері рядка знаходиться diff.

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

Моя порада, не використовуйте повноваження для пошуку відмінностей у файлах. Як зауважив хтось інший, fc працює і працює трохи краще, ніж порівняння-об'єкт, а ще краще - завантаження та використання реальних інструментів, таких як емулятор Unix, про який згадував Mikeage.


Також, схоже, робиться порівняння наборів (тобто ігнорування порядку), як -SyncWindowмаксимальне за замовчуванням. Якщо встановити 0, це не працює так, diffяк ... І коли я передав трубу (... | select-object ...)як вхід, він просто надрукував дурниці, тому я здався.
Миколай

3

Як зазначали інші, якби ви очікували вихідного виводу unix-y, використання псевдоніму powerhell diff дозволило б вам важко впасти. З одного боку, ви повинні тримати його у власне читанні файлів (з gc / get-content). Для іншого показник різниці знаходиться праворуч, далеко від змісту - це кошмар для читання.

Рішення для тих, хто шукає здоровий вихід

  1. отримати справжню різницю (наприклад, від GnuWin32)
  2. редагувати% USERPROFILE% \ Документи \ WindowsPowerShell \ Microsoft.PowerShell_profile.ps1
  3. додайте рядок

    remove-item alias:diff -force

Аргумент-сила необхідний, тому що Powershell є досить цінним щодо цього конкретного вбудованого псевдоніма. Якщо хтось зацікавив, встановивши GnuWin32, я також включив у свій профіль повноважень:

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

Головним чином, тому, що Powershell не розуміє аргументів, які запускаються разом і вводяться, наприклад, "rm -Force -Recurse" - це набагато більше зусиль, ніж "rm -rf".

Powershell має деякі приємні риси, але є деякі речі, які я просто не повинен намагатися зробити для мене.


2

WinMerge - це ще один хороший інструмент розробки на основі GUI.


1
Ось як я це робив у минулому, що є ручним процесом, який я хотів замінити невеликим сценарієм.
Братч

1

Також є Windiff, який пропонує інтерфейс інтерфейсу GUI (чудово підходить для програм CVS / SVN на основі GUI)


1

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

Порівняння-об'єкт призначений для визначення того, чи є 2 об'єкти однаковими для членів. якщо об'єкти є колекціями, то вони трактуються як SETS (див. довідку порівняння-об’єкта), тобто колекції UNORDERED без дублікатів. 2 набори рівні, якщо вони мають однакові елементи членів, незалежно від порядку чи дублювання. Це суттєво обмежує його корисність для порівняння текстових файлів для відмінностей. По-перше, поведінка за замовчуванням збирає відмінності до тих пір, поки весь об'єкт (файл = масив рядків) не перевіряється, таким чином втрачаючи інформацію про положення різниць і затушовуючи, які відмінності поєднуються (і немає поняття номер рядка для SET струн). Використання -synchwindow 0 призведе до того, що різниці видаватимуться у міру їх виникнення, але перешкоджає спробі повторної синхронізації, тому якщо один файл має додатковий рядок, то наступні порівняння рядків можуть вийти з ладу, навіть якщо файли інакше однакові (доки не буде компенсації зайвий рядок в іншому файлі, тим самим переставляючи відповідні лінії). Однак повноваження вкрай універсальні, і корисне порівняння файлів можна здійснити, використовуючи цю функціональність, хоча і ціною значної складності та з деякими обмеженнями щодо вмісту файлів. Якщо вам потрібно порівняти текстові файли з довгими (> 127 символами) рядками та де рядки здебільшого відповідають 1:

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,$_ }) отримує вміст файлу і попередньо додає номер рядка та індикатор файлу (<< або >>) до кожного рядка (використовуючи оператор рядка формату) перед тим, як передати його до розл.
  • -property { $_.substring(9) }каже diff для порівняння кожної пари об'єктів (рядків), ігноруючи перші 9 символів (це номер рядка та показник файлу). При цьому використовується можливість вказувати обчислену властивість (значення блоку сценарію) замість імені властивості.
  • -passthru викликає diff для виведення різних вхідних об'єктів (які включають номер рядка та індикатор файлу) замість різних об'єктів, що порівнюються (які не мають).
  • sort-objectпотім повертає всі рядки в послідовність.
    out-string зупиняє усічення виводу за замовчуванням, щоб відповідати ширині екрану (як зазначив Марк Товерсап), вказавши достатньо велику ширину, щоб уникнути усікання. Зазвичай цей вихід буде розміщений у файлі, який потім переглядається за допомогою редактора прокрутки (наприклад, блокнот).

Примітка

Формат номера рядка {0,6} дає право виправданий пробіл із 6 символами (для сортування). Якщо у файлах більше 999 999 рядків, просто змініть формат, щоб бути ширшим. Для цього також потрібно змінити $_.substringпараметр (на 3 більше, ніж ширина номера рядка) та значення xx вихідного рядка (максимальна довжина рядка + $_.substringпараметр).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.