Bagaimana cara membedakan dua file teks di Windows Powershell?

96

Saya memiliki dua file teks dan ingin menemukan perbedaan di antara mereka menggunakan Windows Powershell. Apakah ada sesuatu yang mirip dengan alat Unix diff yang tersedia? Atau ada cara lain yang belum saya pertimbangkan?

Saya sudah mencoba objek perbandingan, tetapi dapatkan output samar ini:

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

InputObject                                                 SideIndicator
-----------                                                 -------------
two.txt                                                     =>
one.txt                                                     <=
Brian Willis
sumber

Jawaban:

101

Mencari tahu sendiri. Karena Powershell bekerja dengan objek .net daripada teks, Anda perlu menggunakan get-content untuk mengekspos konten file teks. Jadi untuk melakukan apa yang saya coba lakukan dalam pertanyaan, gunakan:

compare-object (get-content one.txt) (get-content two.txt)
Brian Willis
sumber
1
Saya sangat terkejut ketika saya mencoba membandingkan dua file: array angka yang tidak disortir, dan array angka yang sama setelah mengurutkannya. Tidak ada output meskipun file sangat berbeda. Rupanya, objek perbandingan tidak mempertimbangkan pesanan.
cgmb
1
@cgmb - Anda dapat menggunakannya -SyncWindow 0untuk memperbaikinya, saya percaya, meskipun saya tidak yakin apakah itu baru saja diperkenalkan. Tapi itu tidak terlalu pintar tentang itu.
James Ruskin
32

Cara yang lebih sederhana untuk melakukannya adalah dengan menulis:

diff (cat file1) (cat file2)
Alex Y.
sumber
16
Diff dan cat hanyalah alias untuk Compare-Object dan Get-Content di PowerShell. Itu adalah hal yang sama.
Shawn Melton
4
walaupun ini sama dengan jawaban yang diterima, saya lebih suka menggunakan sintaks ini
Elijah W. Gagne
Perhatikan bahwa itu tidak berperilaku seperti * nix diffsama sekali, seperti jawaban lain di sini perhatikan. Dan ketika saya menggunakan ekspresi yang lebih kompleks di tempat catsaya mendapat output yang salah, jadi saya akan bergabung dengan yang lain dalam rekomendasi untuk menghindari melakukan ini di PowerShell jika Anda berasal dari * nix.
Nickolay
29

Atau Anda bisa menggunakan fcperintah DOS seperti ini (Ini menunjukkan output dari kedua file sehingga Anda harus memindai perbedaannya):

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

fcadalah alias untuk cmdlet Format-Kustom jadi pastikan untuk memasukkan perintah sebagaifc.exe . Harap dicatat bahwa banyak utilitas DOS tidak menangani pengkodean UTF-8.

Anda juga dapat menelurkan proses CMD dan menjalankannya fc.

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

Ini menginstruksikan PowerShell untuk memulai proses dengan program 'cmd' menggunakan parameter dalam tanda kutip. Dalam tanda kutip, adalah opsi '/ c' cmd untuk menjalankan perintah dan mengakhiri. Perintah aktual untuk dijalankan oleh cmd dalam proses ini adalah fc filea.txt fileb.txtmengarahkan kembali output ke file diff.txt.

Anda dapat menggunakan DOS fc.exedari dalam PowerShell.

phord350
sumber
2
+1 untuk mengeluarkan DOS ^ _ ^
Jeff Bridgman
1
"fc" tidak berfungsi untuk saya, dan saya tidak menyadari bahwa saya harus menetapkannya sebagai "fc.exe" untuk membedakannya dari Format-Custom. Persis apa yang saya cari. Terima kasih.
Xonatron
Mungkin saya seorang filistin lengkap, tetapi ini tampaknya jauh lebih berguna bagi saya. Ini memecahkan masalah saya dengan sangat baik.
AJ.
Satu-satunya masalah adalah itu TOPAN unik.
iCodeSometime
7

diff pada * nix bukan bagian dari shell, tetapi aplikasi yang terpisah.

Apakah ada alasan Anda tidak bisa menggunakan diff.exe di bawah PowerShell?

Anda dapat mengunduh versi dari paket UnxUtils ( http://unxutils.sourceforge.net/ )

Mikeage
sumber
10
Karena PowerShell disertakan sekarang, tidak ada yang dapat diunduh dan diinstal.
Awal
Saya akhirnya menggunakan git diff, karena saya sudah menginstalnya. Tidak fc.exejuga Compare-Objectmenghasilkan output yang saya harapkan.
Raziel
4

objek-banding (alias diff alias) menyedihkan jika Anda mengharapkannya berperilaku seperti diff unix. Saya mencoba diff (gc file1) (gc file2), dan jika sebuah baris terlalu panjang, saya tidak dapat melihat diff yang sebenarnya dan yang lebih penting, saya tidak bisa mengatakan nomor baris mana diff tersebut aktif.

Ketika saya mencoba menambahkan -passthru, saya sekarang dapat melihat perbedaannya, tetapi saya kehilangan file mana perbedaannya, dan saya masih tidak mendapatkan nomor baris.

Saran saya, jangan gunakan PowerShell untuk menemukan perbedaan dalam file. Seperti orang lain catat, fc bekerja, dan bekerja sedikit lebih baik daripada membandingkan-objek, dan bahkan lebih baik mengunduh dan menggunakan alat nyata seperti emulator unix yang disebutkan Mikeage.

Marc Towersap
sumber
Tampaknya juga melakukan perbandingan set (yaitu mengabaikan pesanan) seperti -SyncWindowyang maksint secara default. Menetapkan bahwa ke 0 tidak membuatnya bekerja seperti diff... Dan ketika saya melewati sebuah pipa (... | select-object ...)sebagai input, itu hanya mencetak omong kosong, jadi saya menyerah.
Nickolay
3

Seperti yang telah dicatat orang lain, jika Anda mengharapkan output unix-y diff, menggunakan powershell diff alias akan mengecewakan Anda. Untuk satu hal, Anda harus memegang tangannya untuk benar-benar membaca file (dengan gc / get-content). Untuk yang lain, indikator perbedaannya ada di kanan, jauh dari konten - itu adalah mimpi buruk keterbacaan.

Solusi bagi siapa pun yang mencari output yang waras adalah

  1. dapatkan perbedaan nyata (mis. dari GnuWin32)
  2. edit% USERPROFILE% \ Documents \ WindowsPowerShell \ Microsoft.PowerShell_profile.ps1
  3. tambahkan baris

    remove-item alias:diff -force

Argumen -force diperlukan karena Powershell sangat berharga tentang alias inbuilt khusus ini. Jika ada yang tertarik, setelah menginstal GnuWin32, saya juga memasukkan yang berikut ini di profil PowerShell saya:

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

Terutama karena Powershell tidak memahami argumen yang dijalankan bersama dan mengetik, misalnya "rm -Force -Recurse" adalah upaya yang jauh lebih banyak daripada "rm -rf".

Powershell memiliki beberapa fitur bagus, tetapi ada beberapa hal yang seharusnya tidak dilakukan untuk saya.

daf
sumber
2

WinMerge adalah alat diff berbasis GUI yang bagus.

Andy White
sumber
1
Ini adalah bagaimana saya melakukannya di masa lalu, yang merupakan proses manual, yang ingin saya ganti dengan skrip kecil.
Awal
1

Ada juga Windiff yang menyediakan antarmuka GUI (bagus untuk digunakan dengan program CVS / SVN berbasis GUI)

saschabeaumont
sumber
1

fc.exelebih baik untuk membandingkan teks karena dirancang untuk bekerja seperti * nix diff, yaitu membandingkan baris secara berurutan, menunjukkan perbedaan aktual dan mencoba menyinkronkan ulang (jika bagian yang berbeda memiliki panjang yang berbeda). Ini juga memiliki beberapa opsi kontrol yang berguna (teks / biner, sensitivitas case, nomor baris, panjang sinkronisasi ulang, ukuran buffer tidak cocok) dan memberikan status keluar (-1 sintaks buruk, 0 file sama, 1 file berbeda, 2 file hilang). Menjadi (sangat) utilitas DOS lama, itu memang memiliki beberapa keterbatasan. Terutama, itu tidak otomatis bekerja dengan Unicode, memperlakukan 0 MSB karakter ASCII sebagai terminator garis sehingga file menjadi urutan 1 baris karakter (@kennycoc: gunakan opsi / U untuk menentukan KEDUA file adalah Unicode, WinXP dan seterusnya ) dan juga memiliki ukuran buffer garis keras 128 karakter (128 byte ASCII,

objek banding dirancang untuk menentukan apakah 2 objek identik dengan anggota. jika objek adalah koleksi maka mereka diperlakukan sebagai SETS (lihat bantuan membandingkan-objek), yaitu koleksi UNORDERED tanpa duplikat. 2 set sama jika mereka memiliki item anggota yang sama terlepas dari pesanan atau duplikasi. Ini sangat membatasi kegunaannya untuk membandingkan file teks untuk perbedaan. Pertama, perilaku default mengumpulkan perbedaan sampai seluruh objek (file = array string) telah diperiksa sehingga kehilangan informasi mengenai posisi perbedaan dan mengaburkan perbedaan mana yang dipasangkan (dan tidak ada konsep nomor baris untuk SET) string). Menggunakan -synchwindow 0 akan menyebabkan perbedaan yang dipancarkan ketika terjadi tetapi menghentikannya dari mencoba menyinkronkan kembali sehingga jika satu file memiliki baris tambahan maka perbandingan baris berikutnya dapat gagal meskipun file tersebut identik (sampai ada kompensasi baris tambahan di file lain dengan demikian menyelaraskan garis yang cocok). Namun, PowerShell sangat fleksibel dan membandingkan file yang bermanfaat dapat dilakukan dengan memanfaatkan fungsi ini, meskipun dengan biaya kompleksitas yang substansial dan dengan beberapa pembatasan pada konten file. Jika Anda perlu membandingkan file teks dengan garis panjang (> 127 karakter) dan di mana garis tersebut paling cocok dengan 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

di mana xx adalah panjang dari garis terpanjang + 9

Penjelasan

  • (gc file | % -begin { $ln=0 } -process { '{0,6}<<:{1}' -f ++$ln,$_ }) mendapatkan konten file dan menambahkan nomor baris dan indikator file (<< atau >>) ke setiap baris (menggunakan operator format string) sebelum meneruskannya ke diff.
  • -property { $_.substring(9) }memberitahu diff untuk membandingkan setiap pasangan objek (string) dengan mengabaikan 9 karakter pertama (yang merupakan nomor baris dan indikator file). Ini memanfaatkan kemampuan untuk menentukan properti yang dihitung (nilai blok skrip) alih-alih nama properti.
  • -passthru menyebabkan diff untuk menampilkan objek input yang berbeda (yang mencakup nomor baris dan indikator file) alih-alih objek yang dibandingkan berbeda (yang tidak).
  • sort-objectlalu letakkan semua garis kembali ke dalam urutan.
    keluar-string menghentikan pemotongan default output agar sesuai dengan lebar layar (seperti dicatat oleh Marc Towersap) dengan menentukan lebar yang cukup besar untuk menghindari pemotongan. Biasanya, output ini akan dimasukkan ke dalam file yang kemudian dilihat menggunakan editor gulir (misalnya notepad).

Catatan

Format nomor baris {0,6} memberikan angka garis 6 karakter yang dapat dibenarkan, dengan spasi tepat (untuk pengurutan). Jika file memiliki lebih dari 999.999 baris maka cukup ubah format menjadi lebih luas. Ini juga membutuhkan pengubahan $_.substringparameter (3 lebih dari lebar nomor baris) dan nilai x-string-out (panjang + $_.substringparameter maksimum ).

codemaster bob
sumber