Linux: เปรียบเทียบโครงสร้างไดเร็กทอรีโดยไม่เปรียบเทียบไฟล์


55

วิธีที่ดีที่สุดและง่ายที่สุดในการเปรียบเทียบโครงสร้างไดเรกทอรีสองรายการโดยไม่เปรียบเทียบข้อมูลในไฟล์คืออะไร ใช้งานได้ดี:

diff -qr dir1 dir2_

แต่มันช้ามากเพราะมันเป็นการเปรียบเทียบไฟล์ด้วย มีสวิตช์สำหรับ diff หรือเครื่องมือ cli อื่น ๆ ให้ทำเช่นนี้หรือไม่?


โดย "โครงสร้างไดเรกทอรี" คุณหมายถึงเพียงเส้นทางไดเรกทอรีหรือเส้นทางของทั้งไดเรกทอรีและไฟล์ที่ไม่ใช่ไดเรกทอรี?
intuited

ใช่โฟลเดอร์และไฟล์
Jonah

1
ในกรณีนี้คุณควรลบ-type dตัวเลือกออกจากคำตอบของ @ slartibartfast หรือดูคำตอบของฉัน
intuited

คำตอบ:


36

ต่อไปนี้ (หากคุณแทนที่ไดเรกทอรีแรกสำหรับ directory1 และที่สองสำหรับ directory2) ควรทำสิ่งที่คุณกำลังมองหาและอย่างรวดเร็ว:

find directory1 -type d -printf "%P\n" | sort > file1
find directory2 -type d -printf "%P\n" | sort | diff - file1

หลักการพื้นฐานคือมันพิมพ์ไดเร็กทอรีทั้งหมดรวมถึงพา ธ ไดเร็กทอรีย่อยที่สัมพันธ์กับไดเร็กทอรี baseN ไดเร็กทอรี

สิ่งนี้อาจล้มลง (สร้างเอาต์พุตที่มีจำนวนมาก) หากคุณมี carriage return ในชื่อไดเร็กทอรีบางชื่อ แต่ไม่ใช่ชื่ออื่น


สิ่งนี้ไม่ดีสำหรับฉันเพราะหากไดเรกทอรีหนึ่งมีโฟลเดอร์ที่มีไฟล์สองสามพันไฟล์อยู่ในรายการทั้งหมดทีละรายการในขณะที่diff -rqเพียงแสดงไดเรกทอรีหลักที่มีอยู่ในหนึ่งและดำเนินการต่อ
Chris Jefferson

ตามที่ได้ชี้ให้เห็น (หลายปีที่ผ่านมา) โดยการหยั่งรู้เพื่อตอบคำถาม OPs ควรลบ -type d เพื่อให้ไฟล์ถูกพิจารณาในการเปรียบเทียบเช่นเดียวกับไดเรกทอรี
user2746401

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

34
vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)

จะให้การแสดงผลที่ดีเคียงข้างกันของลำดับชั้นไดเรกทอรีสองที่มีส่วนทั่วไปใด ๆ พับ


วิธีนี้ล้มเหลวแบบสุ่ม เมื่อ vim อ่าน (หรืออ่านซ้ำ) ตัวอธิบายไฟล์ชั่วคราวจะหายไปแล้ว
Denilson Sá Maia

23

ฉันมักจะใช้rsyncสำหรับงานนี้:

rsync -nav --delete DIR1/ DIR2

ระวังให้มากให้ใช้ตัวเลือก,-naka--dry-run, หรือจะซิงโครไนซ์ (เปลี่ยนเนื้อหาของ) ไดเรกทอรี

สิ่งนี้จะเปรียบเทียบไฟล์ตามเวลาและขนาดของการปรับเปลี่ยนไฟล์ ... ฉันคิดว่านั่นคือสิ่งที่คุณต้องการจริง ๆ หรืออย่างน้อยคุณก็ไม่รังเกียจหากมันเป็นเช่นนั้น? ฉันรู้สึกว่าคุณแค่อยากให้มันเกิดขึ้นเร็วขึ้นไม่ใช่ว่าคุณต้องการที่จะเพิกเฉยต่อความแตกต่างระหว่างเนื้อหาของไฟล์ หากคุณไม่ต้องการแสดงไฟล์ที่แตกต่างที่มีชื่อเหมือนกันฉันคิดว่าการเพิ่ม--ignore-existingตัวเลือกจะทำเช่นนั้น

นอกจากนี้ยังทราบว่ามีการวาง/ในตอนท้ายของDIR1จะทำให้มันเปรียบเทียบไดเรกทอรี DIR1ที่มีเนื้อหาDIR2ของ

ผลลัพธ์จะเป็น verbose เล็กน้อย แต่มันจะแสดงให้คุณเห็นว่าไฟล์ / ไดเร็กตอรี่ใดบ้าง ไฟล์ไดเรกทอรี / ในปัจจุบันDIR2และไม่ได้อยู่ในจะได้รับการวิจารณ์ด้วยคำว่าDIR1deleting

สำหรับบางสถานการณ์คำตอบของ @ slartibartfast อาจจะเหมาะสมกว่าแม้ว่าคุณจะต้องลบ-type dตัวเลือกเพื่อเปิดใช้งานการแสดงรายการไฟล์ที่ไม่ใช่ไดเรกทอรี rsyncจะเร็วขึ้นหากคุณมีไฟล์ / ไดเรกทอรีจำนวนมากที่จะเปรียบเทียบ


คำตอบที่ยอดเยี่ยม ในเอาต์พุตของ rsync เป็นการยากที่จะสังเกตเห็นdeleting...ข้อความ แต่อาจเป็นวิธีที่ดีกว่าวิธีหนึ่งในการเปรียบเทียบไฟล์ในขณะที่ยังคงความเร็ว คำตอบอื่น ๆ ที่นี่จะเร็วขึ้นเมื่อไม่จำเป็นต้องใช้การกระจายไฟล์ ... ตามตัวอย่างของ OP แต่ฉันชอบอันนี้มาก
Joel Mellon

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

อาจเป็นการดีที่จะเรียกใช้กับผู้ใช้ที่มีการเข้าถึงแบบอ่านอย่างเดียว ชอบsudo -u nobody rsync -nav --delete d1 d2โดยมีเงื่อนไขว่าธงสำหรับ 'คนอื่น' อนุญาตให้อ่าน
user1182474

เมื่อใช้งานโซลูชันนี้ฉันได้รับ "กำลังสร้างรายการไฟล์ ... เสร็จแล้ว \ n ส่ง X ไบต์ได้รับ Y ไบต์ไบต์ Z ขนาด / วินาทีโดยรวมคือการเร่งความเร็วคือ B" (โดยที่ฉันใช้แทน XYZAB แทนตัวเลข) นั่นหมายความว่าทุกอย่างเหมือนกันหรือไม่? เนื่องจากมันไม่ได้เอ่ยถึงอะไรที่เฉพาะเจาะจงกว่านี้? ขอบคุณล่วงหน้า
Scott H

เพื่อตอบคำถามของฉันเองฉันทดลองเพิ่มไฟล์ที่แตกต่างกันในแต่ละไฟล์และดูเหมือนว่าไม่มีไฟล์ / dirs เฉพาะที่กล่าวถึงในผลลัพธ์หมายความว่ามันเหมือนกันหมด
Scott H

18

คล้ายกับคำตอบ ls แต่ถ้าคุณติดตั้งแผนผังคุณสามารถทำได้

tree dir1 > out1
tree dir2 > out2
diff out1 out2

7
หรือเพื่อหลีกเลี่ยง tmpfilesdiff <( tree dir1 ) <( tree dir2 )
Joel Mellon

1
ฉันแนะนำให้ใช้ tree กับiflag ซึ่งไม่ได้พิมพ์บรรทัด tree ( tree -i dir1และอื่น ๆ ) หากโครงสร้างไดเรกทอรีแตกต่างกันในที่เดียวไฟล์อื่น ๆ ที่ตรงกันอาจมี|สัญลักษณ์มากขึ้นหรือน้อยลงในเอาต์พุตทรีและ diff จะจับคู่บรรทัดเหล่านั้นแม้ว่าพา ธ ไฟล์จะเหมือนกัน
askewchan

2
diff <(tree -i dir1) <(tree -i dir2) เป็นคำตอบที่ดีที่สุด ฉันอยากจะ downvote คำตอบทั้งหมดที่แนะนำ diff หรือ rsync เนื่องจากคำถามบอกอย่างชัดเจนว่าไม่ต้องอ่านเนื้อหาของไฟล์ หมายเหตุ: คำแนะนำในการใช้สองท่อต้องใช้ช่องว่างระหว่างวงเล็บอย่างระมัดระวังให้ปฏิบัติตามตัวอย่าง เช่นการเปรียบเทียบสองปริมาณ 20G หลังจากการสำรองข้อมูลคำตอบแบบต้นไม้ใช้เวลาประมาณ 5 วินาที คนอื่น ๆ ใช้เวลามากกว่า 20 นาที
Jason Morgan

3

ฉันแค่หาวิธีแก้ปัญหานี้ ทางออกที่ฉันชอบมากที่สุดคือ:

comm <(ls DIR1) <(ls DIR2)

มันให้ 3 คอลัมน์: 1 - ไฟล์เฉพาะใน DIR1, 2 - ไฟล์เฉพาะใน DIR2, 3 - ไฟล์เฉพาะใน DIR3 สำหรับรายละเอียดเพิ่มเติมดูที่โพสต์บล็อกนี้


อยู่ที่ไหนDIR3ระบุ? ทั้งหมดที่ฉันเห็นคือและDIR1 DIR2
Michael Dorst

ฉันพยายามมันและ (จากสิ่งที่ผมสามารถบอกได้) เอาท์พุทคือ: ไฟล์ทั้งหมดเฉพาะในDIR1ในคอลัมน์ 1ไฟล์ทั้งหมดเฉพาะในDIR2ในคอลัมน์ 2และไฟล์ทั้งหมดที่ใช้ร่วมกันโดยทั้งสองในคอลัมน์ 3 นั่นเป็นประโยชน์อย่างมาก แต่คุณรู้หรือไม่ว่ามีวิธีใดที่อาจแยกคอลัมน์ 3ออกและทิ้งความแตกต่างไว้เท่านั้น ฉันมีไฟล์จำนวนมากที่ต้องจัดเรียงและส่วนใหญ่มันเหมือนกัน ฉันไม่ต้องการเห็นสิ่งเดียวกัน
Michael Dorst

1
นอกจากนี้ฉันพบว่าcomm <(ls DIR1) <(ls DIR2)มันไม่ทำงานซ้ำ comm <(ls -R1 DIR1) <(ls -R1 DIR2)สำหรับการที่ผมใช้ ls -Rรวบรวมข้อมูลผ่านไดเรกทอรีซ้ำและls -1(โปรดทราบว่าเป็นหนึ่งไม่ใช่L ) ทำให้lsพิมพ์ชื่อไฟล์เดียวต่อบรรทัด
Michael Dorst

@Michael: comm -3(ดูman comm)
Zaz

2
ls > dir1.txt

ls > dir2.txt

จากนั้นเพียงแค่แตกต่างสองรายการ


ดูเหมือนว่า OP ต้องการสืบทอดเส้นทาง สิ่งนี้จะแตกไฟล์ทั้งหมดในไดเรกทอรีปัจจุบัน เป็นที่ถกเถียงกัน แต่เป็นไปได้ว่าเขาต้องการไดเรกทอรี; เขาอาจต้องการชื่อไฟล์มากกว่าเนื้อหาของไฟล์
intuited

@intuited - คุณพูดถูก ฉันอ่านผิด
MDMarra

2

นี่คือทางออกที่ดีที่สุด

diff --brief -r dir1 dir2

- บทสรุปสลับเฉพาะรายงานว่าไฟล์ต่างกันไม่ใช่รายละเอียดของความแตกต่าง


1
สหกรณ์มีอยู่แล้วในคำถามซึ่งเป็นนามแฝงสำหรับ-q --briefคำตอบนี้ไม่ได้ให้ข้อมูลใหม่ใด ๆ
Michael Dorst

1
OP ไม่ต้องการเปรียบเทียบเนื้อหาไฟล์ But it's really slow because it's comparing files too.
Joel Mellon

1

ใช้ "diff -qr" เพื่อรับไฟล์ต่าง ๆ จากนั้นกรองการเปรียบเทียบไฟล์ด้วย grep เพื่อให้ได้ชื่อไฟล์ที่อยู่ในหนึ่งในไดเรกทอรีเท่านั้น

diff -qr dir1 dir2 | grep -v "Files.*differ" 

1

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

diff <( cd dir1; find * |sort ) <(cd dir2; find * | sort)

-3

ฉันคิดว่า rsync มีเพียง userfull เท่านั้น ทำไม?

diff มีประโยชน์สำหรับโครงสร้างที่เก็บไฟล์และไดเรกทอรีเท่านั้น Diff ไม่ได้ให้รหัสทางออกที่เพียงพอเมื่อเราใช้ symlink ในสถานการณ์นั้น diff สามารถส่งคืนรหัสทางออก 2 ตัวแม้ว่า src และ dst จะเหมือนกัน (เวลา, ขนาด, ชื่อ, เวลาประทับ, ซอฟต์ลิ้งชี้ ฯลฯ )

เป็นครั้งแรก, ระบบไฟล์ไม่รับประกันการสั่งซื้อไฟล์, แม้ว่าเนื้อหาไดเรกทอรีใน src และ dst เหมือนกัน. บางทีคุณควรกรองผลลัพธ์ ls ด้วยการเรียงลำดับ แต่ pure ls แสดงชื่อโหนดเท่านั้น

อาจรวมถึงสคริปต์, diff, cmp, test -X สำหรับประเภทโหนดจะเป็นประโยชน์ แต่โปรดจำไว้ว่าการโอเวอร์โหลดทำโดยการทดสอบ / cmp หลายครั้ง สคริปต์จะช้ามาก

ตามปกติถ้าคุณต้องการข้อมูลแบบง่าย "dirs ไม่เหมือน / ไม่เหมือนกัน" คุณควรใช้ rsync กับตัวเลือก -n (dry) หากคุณต้องการค้นหาสิ่งที่แตกต่างให้ใช้คำสั่ง diff


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