Làm cách nào để tìm khác biệt hai tệp văn bản trong Windows Powershell?


96

Tôi có hai tệp văn bản và muốn tìm sự khác biệt giữa chúng bằng Windows Powershell. Có một cái gì đó tương tự như công cụ tìm khác biệt Unix có sẵn? Hay có một cách khác mà tôi chưa xem xét?

Tôi đã thử so sánh đối tượng, nhưng nhận được kết quả khó hiểu này:

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

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

Câu trả lời:


101

Tìm ra nó bản thân mình. Vì Powershell hoạt động với các đối tượng .net chứ không phải văn bản, bạn cần sử dụng nội dung get để hiển thị nội dung của tệp văn bản. Vì vậy, để thực hiện những gì tôi đã cố gắng làm trong câu hỏi, sử dụng:

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

1
Tôi đã rất ngạc nhiên khi tôi cố gắng so sánh hai tệp: một mảng số chưa được sắp xếp và cùng một mảng số sau khi sắp xếp chúng. Không có đầu ra mặc dù các tập tin rất khác nhau. Rõ ràng, đối tượng so sánh không xem xét trật tự.
cgmb

1
@cgmb - Tôi có thể sử dụng -SyncWindow 0để khắc phục điều đó, tôi tin, mặc dù tôi không chắc nếu nó chỉ được giới thiệu gần đây. Nó không đặc biệt thông minh về nó, mặc dù.
James Ruskin

32

Một cách đơn giản hơn để làm là viết:

diff (cat file1) (cat file2)

16
Diff và cat chỉ là bí danh cho So sánh-Object và Get-Content trong PowerShell. Đó là điều tương tự.
Shawn Melton

4
mặc dù điều này giống như câu trả lời được chấp nhận, tôi thích sử dụng cú pháp này hơn
Elijah W. Gagne

Lưu ý rằng nó hoàn toàn không hoạt động như * nix diff, như các câu trả lời khác ở đây lưu ý. Và khi tôi sử dụng một biểu thức phức tạp hơn thay cho cattôi có đầu ra không chính xác, vì vậy tôi sẽ tham gia các biểu thức khác trong đề xuất để tránh thực hiện điều này trong PowerShell nếu bạn đến từ * nix.
Nickolay

29

Hoặc bạn có thể sử dụng fclệnh DOS như vậy (Điều này hiển thị đầu ra của cả hai tệp để bạn sẽ phải quét tìm sự khác biệt):

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

fclà bí danh cho lệnh ghép ngắn Format-Custom, vì vậy hãy chắc chắn nhập lệnh dưới dạngfc.exe . Xin lưu ý rằng nhiều tiện ích DOS không xử lý mã hóa UTF-8.

Bạn cũng có thể sinh ra một quy trình CMD và chạy fctrong đó.

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

Điều này hướng dẫn PowerShell bắt đầu một quy trình với chương trình 'cmd' bằng cách sử dụng các tham số trong dấu ngoặc kép. Trong dấu ngoặc kép, là tùy chọn '/ c' cmd để chạy lệnh và chấm dứt. Lệnh thực tế để chạy bởi cmd trong quá trình này là fc filea.txt fileb.txtchuyển hướng đầu ra đến tệp diff.txt.

Bạn có thể sử dụng DOS fc.exetừ bên trong powershell.


2
+1 để mang ra DOS ^ _ ^
Jeff Bridgman

1
"fc" không hoạt động với tôi và tôi không nhận ra mình phải chỉ định nó là "fc.exe" để phân biệt với Format-Custom. Chính xác những gì tôi đang tìm kiếm. Cảm ơn.
Xonatron

Có lẽ tôi là một người hoàn toàn phàm tục, nhưng điều này dường như hữu dụng hơn nhiều đối với tôi. Nó giải quyết vấn đề của tôi rất độc đáo.
AJ.

Vấn đề duy nhất là HATE unicode.
iCodeSometime

7

diff trên * nix không phải là một phần của shell, mà là một ứng dụng riêng biệt.

Có bất kỳ lý do nào bạn không thể sử dụng diff.exe trong PowerShell không?

Bạn có thể tải xuống một phiên bản từ gói UnxUtils ( http://unxutils.sourceforge.net/ )


10
Vì PowerShell được bao gồm ngay bây giờ, không có gì để tải xuống và cài đặt.
Bratch

Tôi vừa mới sử dụng git diff, vì tôi đã cài đặt nó. Không sản xuất fc.execũng không Compare-Objectmong đợi.
Raziel

4

so sánh đối tượng (còn gọi là bí danh diff) là thảm hại nếu bạn mong đợi nó hoạt động giống như một unix diff. Tôi đã thử diff (gc file1) (gc file2) và nếu một dòng quá dài, tôi không thể thấy diff thực tế và quan trọng hơn, tôi không thể biết số khác của dòng đó là gì.

Khi tôi thử thêm -passthru, bây giờ tôi có thể thấy sự khác biệt, nhưng tôi mất tập tin khác biệt và tôi vẫn không nhận được số dòng.

Lời khuyên của tôi, đừng sử dụng powershell để tìm sự khác biệt trong các tập tin. Như một người khác đã lưu ý, fc hoạt động và hoạt động tốt hơn một chút so với đối tượng so sánh, và thậm chí tốt hơn là tải xuống và sử dụng các công cụ thực như trình giả lập unix mà Mikeage đã đề cập.


Nó cũng xuất hiện để thực hiện một so sánh thiết lập (tức là bỏ qua thứ tự) như -SyncWindowlà tối đa theo mặc định. Đặt thành 0 cũng không làm cho nó hoạt động giống như diff... Và khi tôi chuyển một đường ống (... | select-object ...)làm đầu vào, nó chỉ in vô nghĩa, vì vậy tôi đã từ bỏ.
Nickolay

3

Như những người khác đã lưu ý, nếu bạn đang mong đợi một đầu ra khác biệt unix-y, sử dụng bí danh diffhell diff sẽ khiến bạn thất vọng. Đối với một điều, bạn phải nắm trong tay thực sự đọc các tệp (với gc / get-content). Mặt khác, chỉ báo khác biệt nằm ở bên phải, cách xa nội dung - đó là một cơn ác mộng dễ đọc.

Giải pháp cho bất cứ ai tìm kiếm một đầu ra lành mạnh là

  1. có được một sự khác biệt thực sự (ví dụ từ GnuWin32)
  2. chỉnh sửa% USERPROFILE% \ Documents \ WindowsPowerShell \ Microsoft.PowerShell_profile.ps1
  3. thêm dòng

    remove-item alias:diff -force

Đối số-Force là bắt buộc vì Powershell khá quý về bí danh sẵn có cụ thể này. Nếu bất cứ ai quan tâm, đã cài đặt GnuWin32, tôi cũng bao gồm những điều sau đây trong hồ sơ quyền hạn của mình:

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

Chủ yếu là vì Powershell không hiểu các đối số được chạy cùng nhau và gõ, ví dụ "rm -Force -Recurse" là nỗ lực hơn nhiều so với "rm -rf".

Powershell có một số tính năng tốt, nhưng có một số điều không nên cố gắng làm cho tôi.


2

WinMerge là một công cụ khác dựa trên GUI tốt.


1
Đây là cách tôi đã làm trong quá khứ, đây là một quy trình thủ công, mà tôi muốn thay thế bằng một tập lệnh nhỏ.
Bratch

1

Ngoài ra còn có Windiff cung cấp giao diện khác biệt GUI (rất phù hợp để sử dụng với các chương trình CVS / SVN dựa trên GUI)


1

fc.exetốt hơn cho việc so sánh văn bản vì nó được thiết kế để hoạt động như * nix diff, tức là so sánh các dòng một cách tuần tự, cho thấy sự khác biệt thực tế và cố gắng đồng bộ hóa lại (nếu các phần khác nhau có độ dài khác nhau). Nó cũng có một số tùy chọn điều khiển hữu ích (văn bản / nhị phân, độ nhạy trường hợp, số dòng, độ dài đồng bộ hóa, kích thước bộ đệm không khớp) và cung cấp trạng thái thoát (-1 cú pháp xấu, 0 tệp giống nhau, 1 tệp khác nhau, thiếu 2 tệp). Là một tiện ích DOS (rất) cũ, nó có một vài hạn chế. Đáng chú ý nhất là nó không tự động hoạt động với Unicode, coi 0 MSB của các ký tự ASCII là dấu kết thúc dòng để tệp trở thành một chuỗi gồm 1 dòng ký tự (@kennycoc: sử dụng tùy chọn / U để chỉ định các tệp BOTH là Unicode, WinXP trở đi ) và nó cũng có kích thước bộ đệm dòng cứng là 128 ký tự (128 byte ASCII,

đối tượng so sánh được thiết kế để xác định xem 2 đối tượng có giống thành viên không. nếu các đối tượng là các bộ sưu tập thì chúng được coi là SETS (xem đối tượng trợ giúp so sánh), tức là các bộ sưu tập UNORDERED không có bản sao. 2 bộ bằng nhau nếu chúng có cùng các mục thành viên không phân biệt thứ tự hoặc trùng lặp. Điều này hạn chế nghiêm trọng tính hữu ích của nó để so sánh các tệp văn bản cho sự khác biệt. Đầu tiên, hành vi mặc định thu thập các khác biệt cho đến khi toàn bộ đối tượng (tệp = mảng chuỗi) đã được kiểm tra, do đó làm mất thông tin liên quan đến vị trí của các khác biệt và che khuất sự khác biệt nào được ghép nối (và không có khái niệm về số dòng cho SET của chuỗi). Việc sử dụng -synchwindow 0 sẽ khiến các khác biệt được phát ra khi chúng xảy ra nhưng ngăn không cho nó cố gắng đồng bộ hóa lại, vì vậy nếu một tệp có thêm một dòng thì việc so sánh dòng tiếp theo có thể thất bại ngay cả khi các tệp giống hệt nhau (cho đến khi có bù trừ dòng bổ sung trong tập tin khác do đó sắp xếp lại các dòng phù hợp). Tuy nhiên, powershell cực kỳ linh hoạt và việc so sánh tệp hữu ích có thể được thực hiện bằng cách sử dụng chức năng này, mặc dù phải trả giá bằng sự phức tạp đáng kể và với một số hạn chế về nội dung của các tệp. Nếu bạn cần so sánh các tệp văn bản với các dòng dài (> 127 ký tự) và trong đó các dòng chủ yếu khớp với 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

Trong đó xx là độ dài của dòng dài nhất + 9

Giải trình

  • (gc file | % -begin { $ln=0 } -process { '{0,6}<<:{1}' -f ++$ln,$_ }) lấy nội dung của tệp và thêm số dòng và chỉ báo tệp (<< hoặc >>) cho mỗi dòng (sử dụng toán tử chuỗi định dạng) trước khi chuyển nó sang diff.
  • -property { $_.substring(9) }báo cho diff để so sánh từng cặp đối tượng (chuỗi) bỏ qua 9 ký tự đầu tiên (là số dòng và chỉ báo tệp). Điều này sử dụng khả năng chỉ định một thuộc tính được tính toán (giá trị của khối tập lệnh) thay vì tên của một thuộc tính.
  • -passthru gây ra khác biệt cho đầu ra các đối tượng đầu vào khác nhau (bao gồm số dòng và chỉ báo tệp) thay vì các đối tượng so sánh khác nhau (không có).
  • sort-objectsau đó đặt tất cả các dòng trở lại thành chuỗi.
    out-string dừng việc cắt ngắn mặc định của đầu ra để vừa với chiều rộng màn hình (như được lưu ý bởi Marc Towersap) bằng cách chỉ định chiều rộng đủ lớn để tránh cắt ngắn. Thông thường, đầu ra này sẽ được đưa vào một tệp mà sau đó được xem bằng trình chỉnh sửa cuộn (ví dụ: notepad).

Ghi chú

Định dạng số dòng {0,6} cung cấp một số dòng ký tự 6 ký tự được đệm hợp lý, đúng chỗ (để sắp xếp). Nếu các tệp có hơn 999.999 dòng thì chỉ cần thay đổi định dạng để rộng hơn. Điều này cũng yêu cầu thay đổi $_.substringtham số (nhiều hơn 3 chiều rộng số dòng) và giá trị xx ngoài chuỗi (độ dài dòng tối đa + $_.substringtham số).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.