เปรียบเทียบสองไดเร็กทอรีซ้ำกับ diff -r โดยไม่ต้องเอาต์พุตบนลิงก์ที่เสียหาย


38

ฉันใช้diff -r a bเพื่อเปรียบเทียบไดเรกทอรีaและbซ้ำ ๆ มันมักจะเกิดขึ้น แต่ที่มีบางส่วนที่ขาดการเชื่อมโยง (ลิงค์เสียเดียวกันทั้งและไดเรกทอรีและชี้ไปที่เดียวกันเป้าหมายที่ไม่ใช่ที่มีอยู่)

diffจะแสดงข้อความแสดงข้อผิดพลาดสำหรับกรณีเหล่านั้นและออกด้วยรหัสทางออกที่ไม่เป็นศูนย์ แต่ฉันต้องการให้มันเงียบและออกด้วย 0 เนื่องจากไดเรกทอรีนั้นเหมือนกันในหนังสือของฉัน

ฉันจะทำสิ่งนั้นได้อย่างไร


คุณยังต้องการเปรียบเทียบ symlink (และระบุว่าเทียบเท่า แต่ใช้งานไม่ได้) หรือเป็นที่ยอมรับหรือไม่ที่จะละเว้น symlink ทั้งหมดเมื่อทำสิ่งนี้แตกต่างกัน?
ire_and_curses

เปรียบเทียบและระบุว่าเทียบเท่าฉันไม่สนใจว่าพวกเขาจะแตก ฉันแค่พยายามตรวจสอบว่า rsync ของฉันทำงาน
Marcus Junius Brutus

คำตอบ:


24

สำหรับรุ่น 3.3 หรือสูงกว่าของdiffคุณควรใช้--no-dereferenceตัวเลือกที่อธิบายไว้ในคำตอบของพีทฮาร์ลาน

น่าเสียดายที่เวอร์ชันเก่ากว่าdiff ไม่สนับสนุนการละเว้น symlink :

ไฟล์บางไฟล์ไม่ใช่ไดเรกทอรีหรือไฟล์ปกติ: เป็นไฟล์ที่ผิดปกติเช่นลิงก์สัญลักษณ์ไฟล์พิเศษของอุปกรณ์ชื่อไปป์และซ็อกเก็ต ขณะนี้diffถือว่าลิงก์สัญลักษณ์เช่นไฟล์ปกติ มันจะถือว่าไฟล์พิเศษอื่น ๆ เช่นไฟล์ปกติหากมีการระบุไว้ที่ระดับบนสุด แต่เพียงรายงานสถานะของพวกเขาเมื่อเปรียบเทียบไดเรกทอรี ซึ่งหมายความว่าpatchไม่สามารถแสดงการเปลี่ยนแปลงของไฟล์ดังกล่าวได้ ตัวอย่างเช่นหากคุณเปลี่ยนไฟล์ที่ลิงก์สัญลักษณ์ชี้ไปจะdiffแสดงผลลัพธ์ที่แตกต่างระหว่างสองไฟล์แทนการเปลี่ยนเป็นลิงก์สัญลักษณ์

diffควรรายงานการเปลี่ยนแปลงไฟล์พิเศษเป็นทางเลือกและpatchควรขยายเพื่อทำความเข้าใจกับส่วนขยายเหล่านี้

หากสิ่งที่คุณต้องการคือการยืนยัน rsync (และอาจแก้ไขสิ่งที่ขาดหายไป) จากนั้นคุณสามารถเรียกใช้คำสั่ง rsync ได้อีกครั้ง หากคุณไม่ต้องการทำเช่นนั้นให้ตรวจสอบการรวมไดเรกทอรีอาจเพียงพอ

หากคุณต้องการทำสิ่งนี้จริงๆdiffคุณสามารถใช้findข้ามการเชื่อมโยงและเรียกใช้แต่ละไฟล์แยกกัน ส่งผ่านไดเรกทอรีaและb ของคุณเป็นอาร์กิวเมนต์:

#!/bin/bash
# Skip files in $1 which are symlinks
for f in `find $1/* ! -type l`
do
    # Suppress details of differences
    diff -rq $f $2/${f##*/}
done

หรือเป็นหนึ่งซับ:

for f in `find a/* ! -type l`;do diff -rq $f b/${f##*/};done

นี้จะระบุไฟล์ที่แตกต่างกันในเนื้อหาหรือไฟล์ที่อยู่ในแต่ไม่ได้อยู่ในข

โปรดทราบว่า:

  • เนื่องจากเรากำลังข้าม symlinks ทั้งหมดนี้จะไม่แจ้งให้ทราบถ้าชื่อ symlink ไม่ได้อยู่ในข หากคุณจำเป็นที่คุณจะต้องเป็นครั้งที่สองหาผ่านเพื่อแจ้ง symlinks ทั้งหมดแล้วอย่างชัดเจนตรวจสอบสำหรับการดำรงอยู่ของพวกเขาในข
  • ไฟล์พิเศษในจะไม่ถูกระบุตั้งแต่รายการที่มีการสร้างขึ้นมาจากเนื้อหาของ นี่อาจไม่ใช่ปัญหาสำหรับสถานการณ์ของคุณrsync

สคริปต์ที่เสนอไม่สามารถใช้งานซ้ำสำหรับไดเรกทอรีใด ๆ ที่มีอยู่ในไดเรกทอรี 'a' (เส้นทางที่สร้างขึ้นสำหรับ 'b' โดยใช้ b / $ {f ## *} ไม่ถูกต้อง)
Marcus Junius Brutus

@MarcusJuniusBrutus - ใช่คุณพูดถูก ฉันคิดว่าทางออกคือการลบ # เช่นfor f in หา a / *! ;do echo $f b/${f#*/};doneL ชนิด ฉันไม่มีเวลาที่จะทดสอบสิ่งนี้ในตอนนี้ แจ้งให้เราทราบหากใช้งานได้
ire_and_curses

มันจะดีกว่า แต่มันก็ยังทำให้ไฟล์ในหลาย ๆ กรณีสับสน สคริปต์ (ที่ลบ # ออก) จะต้องเรียกใช้จากไดเรกทอรีโดยตรงเหนือ 'a' เพื่อให้ทำงานได้
Marcus Junius Brutus

คำตอบนี้จะล้าสมัยเมื่อใช้ GNU diff 3.3 (ดูการโพสต์ด้านล่าง)
แบร์นกลอส

สคริปต์ข้างต้นมีปัญหาหลายประการเนื่องจากพบชื่อไฟล์ทั้งหมดก่อนและส่งไปยังบรรทัดคำสั่งที่ขยายเพิ่ม (1) มันจะทำงานกับกลุ่มไฟล์ขนาดเล็กเท่านั้น (2) ชื่อไฟล์ที่มีอักขระพิเศษ (แม้แต่เว้นวรรค) จะไม่ถูกประมวลผล (3) ใช้$(xxx)แทน backticks เสมอ ความสมมาตรของ Backticks ทำให้พวกเขาอ่านน้อยลงและป้องกันการซ้อนกัน เกี่ยวกับ 1 และ 2 ดูstackoverflow.com/questions/11366184/…
Stéphane Gourichon

19

ตั้งแต่เวอร์ชั่น 3.3 GNU diffสนับสนุนการยกเลิกการอ้างอิง symlink แต่เปรียบเทียบเส้นทางที่ชี้ไป

ติดตั้ง GNU diffutils> = 3.3 และใช้--no-dereferenceตัวเลือก; ไม่มีตัวเลือกสั้น ๆ สำหรับสิ่งนั้น

การวินิจฉัยจะเงียบหากเท่ากับหรือ:

ลิงก์สัญลักษณ์/tmp/noderef/a/symlinkและ/tmp/noderef/b/symlinkแตกต่างกัน


ตอนนี้ถ้าเพียง แต่มันจะแสดงการเปลี่ยนแปลงเนื้อหาราวกับว่า symlink เป็นไฟล์ปกติ ... : - /
lindes

6

คุณสามารถใช้เวอร์ชันที่ใหม่กว่าของ diff

diffใน GNU diffutils3.3 รวมถึง--no-dereferenceตัวเลือกที่ช่วยให้คุณสามารถเปรียบเทียบ symlinks ตัวเองมากกว่าเป้าหมายของพวกเขา มันรายงานว่าพวกเขาต่างกันเงียบถ้าพวกเขาเห็นด้วยและไม่สนใจว่าพวกเขาแตก

ฉันไม่รู้ว่าเมื่อใดที่เพิ่มตัวเลือก มันไม่ได้อยู่ใน 2.8.1


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