ฉันจะแตกไฟล์ข้อความสองไฟล์ใน 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เพื่อแก้ไขปัญหานี้ได้ฉันเชื่อว่าแม้ว่าฉันไม่แน่ใจว่าจะมีการเปิดตัวเมื่อเร็ว ๆ นี้ก็ตาม ถึงแม้ว่ามันจะไม่ฉลาดเท่าไรนัก
James Ruskin

32

วิธีที่ง่ายกว่าคือการเขียน:

diff (cat file1) (cat file2)

15
Diff และ cat เป็นเพียงนามแฝงสำหรับเปรียบเทียบวัตถุและรับเนื้อหาใน PowerShell มันเป็นสิ่งเดียวกัน
Shawn Melton

4
แม้จะเป็นสิ่งเดียวกันกับคำตอบที่ได้รับการยอมรับ แต่ฉันชอบใช้ไวยากรณ์นี้มากขึ้น
Elijah W. Gagne

โปรดทราบว่ามันไม่ได้ทำงานเหมือน * ระวังdiffเลยเช่นเดียวกับคำตอบอื่น ๆ ที่นี่หมายเหตุ และเมื่อฉันใช้การแสดงออกที่ซับซ้อนมากขึ้นแทนcatฉันได้รับผลลัพธ์ที่ไม่ถูกต้องดังนั้นฉันจะเข้าร่วมคนอื่น ๆ ในคำแนะนำเพื่อหลีกเลี่ยงการทำสิ่งนี้ใน PowerShell ถ้าคุณมาจาก * ระวัง
Nickolay

29

หรือคุณสามารถใช้fcคำสั่งDOS อย่าง (แสดงผลของไฟล์ทั้งสองดังนั้นคุณจะต้องสแกนหาความแตกต่าง):

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

fcเป็นนามแฝงสำหรับใช้ cmdlet 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.txtdiff.txt

คุณสามารถใช้ DOS fc.exeจากภายใน powershell


2
+1 เพื่อนำ DOS ออกมา ^ _ ^
Jeff Bridgman

1
"fc" ไม่ทำงานสำหรับฉันและฉันไม่ทราบว่าฉันต้องระบุว่าเป็น "fc.exe" เพื่อแยกความแตกต่างจาก Format-Custom สิ่งที่ฉันกำลังมองหา ขอบคุณ
Xonatron

บางทีฉันอาจเป็นคนฟิลิสเตีย แต่ดูเหมือนว่าฉันจะเป็นประโยชน์มากกว่านี้มาก มันแก้ไขปัญหาของฉันได้อย่างดีมาก
AJ

ปัญหาเดียวคือมันเกลียดยูนิโค้ด
iCodeSometime

7

diff on * nix ไม่ได้เป็นส่วนหนึ่งของเชลล์ แต่เป็นแอปพลิเคชันแยกต่างหาก

มีเหตุผลใดที่คุณไม่สามารถใช้ diff.exe ใน PowerShell ได้หรือไม่

คุณสามารถดาวน์โหลดเวอร์ชันได้จากแพ็คเกจ UnxUtils ( http://unxutils.sourceforge.net/ )


10
เนื่องจาก PowerShell รวมอยู่ด้วยตอนนี้จึงไม่มีอะไรให้ดาวน์โหลดและติดตั้ง
Bratch

ฉันเพิ่งจบการใช้git diffเพราะฉันติดตั้งแล้ว ทั้งfc.exeมิได้Compare-Objectผลิตการส่งออกที่คาดผม
Raziel

4

Compare-object (นามแฝง diff ที่รู้จักกัน) คือน่าสงสารถ้าคุณคาดหวังว่ามันจะทำตัวเหมือนยูนิกซ์ ฉันลอง diff (gc file1) (gc file2) และถ้าบรรทัดยาวเกินไปฉันไม่สามารถเห็น diff จริงและที่สำคัญกว่านั้นฉันไม่สามารถบอกได้ว่าหมายเลขบรรทัดใดที่ diff อยู่

เมื่อฉันลองเพิ่ม -passthru ตอนนี้ฉันสามารถเห็นความแตกต่างได้ แต่ฉันสูญเสียไฟล์ที่มีความแตกต่างอยู่และฉันยังไม่ได้รับหมายเลขบรรทัด

คำแนะนำของฉันอย่าใช้ PowerShell เพื่อค้นหาความแตกต่างในไฟล์ อย่างที่คนอื่นตั้งข้อสังเกต fc ทำงานและทำงานได้ดีกว่าการเปรียบเทียบวัตถุและดีกว่านั้นคือการดาวน์โหลดและการใช้เครื่องมือจริงเช่น unix emulator ที่ Mikeage กล่าวถึง


นอกจากนี้ยังปรากฏขึ้นเพื่อทำการเปรียบเทียบการตั้งค่า (เช่นละเว้นคำสั่งซื้อ) ตามที่-SyncWindowเป็น maxint โดยค่าเริ่มต้น การตั้งค่าเป็น 0 ไม่ได้ทำให้มันเหมือนdiffกัน ... และเมื่อฉันผ่านไปป์(... | select-object ...)เป็นอินพุตมันก็แค่พิมพ์ไร้สาระดังนั้นฉันจึงยอมแพ้
Nickolay

3

ดังที่คนอื่น ๆ ได้กล่าวไว้หากคุณคาดหวังว่าจะได้เอาต์พุต unix-y diff การใช้ชื่อแทนต่าง ๆ ของ powershell จะทำให้คุณผิดหวัง สิ่งหนึ่งที่คุณต้องถือไว้คือการอ่านไฟล์ (ด้วย gc / get-content) อีกตัวบ่งชี้ความแตกต่างอยู่ทางด้านขวาห่างจากเนื้อหา - เป็นฝันร้ายที่อ่านง่าย

วิธีแก้ปัญหาสำหรับทุกคนที่มองหาผลลัพธ์ที่มีสติคือ

  1. รับความแตกต่างที่แท้จริง (เช่นจาก GnuWin32)
  2. แก้ไข% USERPROFILE% \ Documents \ WindowsPowerShell \ Microsoft.PowerShell_profile.ps1
  3. เพิ่มบรรทัด

    remove-item alias:diff -force

จำเป็นต้องใช้อาร์กิวเมนต์ -force เนื่องจาก Powershell ค่อนข้างมีค่าเกี่ยวกับนามแฝง inbuilt นี้โดยเฉพาะ หากใครสนใจมีการติดตั้ง GnuWin32 ฉันยังรวมถึงต่อไปนี้ในโปรไฟล์ PowerShell ของฉัน:

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

สาเหตุหลักมาจาก Powershell ไม่เข้าใจอาร์กิวเมนต์ที่ทำงานร่วมกันและพิมพ์ตัวอย่างเช่น "rm -Force -Recurse" เป็นความพยายามมากกว่า "rm -rf"

Powershell มีคุณสมบัติที่ดี แต่มีบางสิ่งที่ไม่ควรทำเพื่อฉัน


2

WinMergeเป็นเครื่องมือ diff ที่ใช้ GUI ได้ดีอีกชนิดหนึ่ง


1
นี่คือวิธีที่ฉันทำในอดีตซึ่งเป็นกระบวนการแบบแมนนวลที่ฉันต้องการแทนที่ด้วยสคริปต์ขนาดเล็ก
Bratch

1

นอกจากนี้ยังมีWindiffซึ่งมีส่วนต่อประสาน GUI (เหมาะสำหรับใช้กับโปรแกรม CVS / SVN ที่ใช้ GUI)


1

fc.exeจะดีกว่าสำหรับการเปรียบเทียบข้อความเนื่องจากมันออกแบบมาเพื่อทำงานเช่น * nix diff คือเปรียบเทียบบรรทัดตามลำดับแสดงความแตกต่างที่เกิดขึ้นจริงและพยายามซิงโครไนซ์อีกครั้ง (หากส่วนต่างกันมีความยาวต่างกัน) นอกจากนี้ยังมีตัวเลือกการควบคุมที่มีประโยชน์ (ข้อความ / ไบนารีความไวตัวพิมพ์เล็กหมายเลขบรรทัดความยาวการซิงโครไนซ์ขนาดบัฟเฟอร์ไม่ตรงกัน) และให้สถานะการออก (ไวยากรณ์ที่ไม่ดี -1, 0 ไฟล์เดียวกัน 1 ไฟล์แตกต่างกัน เนื่องจากเป็นยูทิลิตี้ DOS เก่า (มาก) จึงมีข้อ จำกัด เล็กน้อย โดยเฉพาะอย่างยิ่งมันไม่ทำงานกับ Unicode โดยอัตโนมัติรักษา 0 MSB ของอักขระ ASCII เป็นตัวยุติบรรทัดดังนั้นไฟล์จะกลายเป็นลำดับของอักขระ 1 บรรทัด (@kennycoc: ใช้ตัวเลือก / U เพื่อระบุไฟล์ทั้งสองเป็น Unicode, WinXP เป็นต้นไป ) และมันก็มีขนาดบัฟเฟอร์ฮาร์ดไลน์ที่ 128 อักขระ (128 ไบต์ ASCII,

Compare-object ได้รับการออกแบบมาเพื่อตรวจสอบว่า 2 วัตถุเป็นสมาชิกที่ฉลาดเหมือนกัน ถ้าวัตถุนั้นเป็นคอลเลกชันก็จะถือว่าเป็นชุด (ดู help help-object) เช่นคอลเลกชัน UNORDERED โดยไม่ซ้ำกัน 2 ชุดมีค่าเท่ากันหากมีรายการสมาชิกเดียวกันโดยไม่คำนึงถึงลำดับหรือการทำซ้ำ ข้อ จำกัด นี้มีประโยชน์อย่างมากสำหรับการเปรียบเทียบไฟล์ข้อความสำหรับความแตกต่าง ประการแรกพฤติกรรมเริ่มต้นจะรวบรวมความแตกต่างจนกระทั่งวัตถุทั้งหมด (ไฟล์ = อาร์เรย์ของสตริง) ได้รับการตรวจสอบจึงสูญเสียข้อมูลเกี่ยวกับตำแหน่งของความแตกต่างและปิดบังความแตกต่างที่ถูกจับคู่ (และไม่มีแนวคิดของหมายเลขบรรทัดสำหรับตลาดหลักทรัพย์ ของสตริง) การใช้ -synchwindow 0 จะทำให้เกิดความแตกต่างในขณะที่เกิดขึ้น แต่พยายามหยุดการซิงโครไนซ์อีกครั้งดังนั้นหากไฟล์หนึ่งมีบรรทัดพิเศษการเปรียบเทียบบรรทัดถัดไปอาจล้มเหลวแม้ว่าไฟล์นั้นจะเหมือนกัน (จนกว่าจะมีการชดเชย บรรทัดพิเศษในไฟล์อื่นจึงจัดแนวบรรทัดที่ตรงกัน) อย่างไรก็ตาม PowerShell นั้นมีความหลากหลายอย่างมากและการเปรียบเทียบไฟล์ที่มีประโยชน์สามารถทำได้โดยการใช้ฟังก์ชั่นนี้แม้ว่าจะมีค่าใช้จ่ายของความซับซ้อนมากมายและมีข้อ จำกัด บางประการเกี่ยวกับเนื้อหาของไฟล์ หากคุณต้องการเปรียบเทียบไฟล์ข้อความที่มีเส้นยาว (> 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,$_ }) รับเนื้อหาของไฟล์และเติมหมายเลขบรรทัดและตัวบ่งชี้ไฟล์ (<< หรือ >>) ให้กับแต่ละบรรทัด (ใช้โอเปอเรเตอร์สตริงรูปแบบ) ก่อนส่งต่อไปยัง diff
  • -property { $_.substring(9) }บอกให้ diff เปรียบเทียบแต่ละคู่ของออบเจ็กต์ (สตริง) โดยไม่สนใจอักขระ 9 ตัวแรก (ซึ่งเป็นหมายเลขบรรทัดและตัวบ่งชี้ไฟล์) สิ่งนี้ใช้ความสามารถในการระบุคุณสมบัติที่คำนวณได้ (ค่าของบล็อกสคริปต์) แทนที่จะเป็นชื่อของคุณสมบัติ
  • -passthru ทำให้ diff แตกต่างกันไปกับวัตถุอินพุตที่แตกต่างกัน (ซึ่งรวมถึงหมายเลขบรรทัดและตัวบ่งชี้ไฟล์) แทนที่จะเป็นวัตถุเปรียบเทียบที่แตกต่างกัน (ซึ่งไม่)
  • sort-objectจากนั้นใส่บรรทัดทั้งหมดกลับเป็นลำดับ
    out-string หยุดการตัดทอนเริ่มต้นของเอาท์พุทให้พอดีกับความกว้างของหน้าจอ (ตามที่ระบุไว้โดย Marc Towersap) โดยการระบุความกว้างที่ใหญ่พอที่จะหลีกเลี่ยงการตัดทอน โดยปกติเอาต์พุตนี้จะถูกใส่ลงในไฟล์ซึ่งจะถูกดูโดยใช้ตัวเลื่อนการเลื่อน (เช่น notepad)

บันทึก

รูปแบบหมายเลขบรรทัด {0,6} ให้ความถูกต้องอย่างสมเหตุสมผลช่องว่างขนาด 6 อักขระ (สำหรับการจัดเรียง) หากไฟล์มีมากกว่า 999,999 บรรทัดให้เปลี่ยนรูปแบบให้กว้างขึ้น สิ่งนี้ยังต้องการการแก้ไข$_.substringพารามิเตอร์ (มากกว่าความกว้างของหมายเลขบรรทัด 3) และค่า xx ของ out-string (ความยาวบรรทัด + $_.substringพารามิเตอร์สูงสุด)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.