rsync เปรียบเทียบไดเรกทอรี?


63

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

ls -alRและdiffไม่มีตัวเลือกที่นี่เนื่องจากมีฮาร์ดลิงก์ในแหล่งที่มาทำให้ทุกบรรทัดแตกต่างกัน (แน่นอนฉันสามารถลบคอลัมน์นี้ด้วย perl.)


ที่คล้ายกัน: serverfault.com/questions/62364/…
reinierpost

คำตอบ:


46

คุณจะต้องทำงานบางอย่างเหมือนกัน rsync -avun --deleteทั้งสองทิศทาง

แต่คุณพยายามทำอะไรจริงๆ

อัปเดต :

rsync -avun --delete $TARGET $SOURCE |grep "^deleting " จะให้รายการของไฟล์ที่ไม่มีอยู่ในไดเรกทอรีเป้าหมาย

"grep delet" เพราะแต่ละบรรทัดพิมพ์: ลบ ing ..file ..

rsync -avun $SOURCE $TARGET จะให้รายชื่อไฟล์ "แตกต่าง" (รวมถึงไฟล์ใหม่)


49

หากต้องการเพิ่มคำตอบของ Nils (สำหรับทุกคนที่เจอสิ่งนี้ผ่าน Google) โดยค่าเริ่มต้นrsyncจะเปรียบเทียบขนาดไฟล์และเวลาการแก้ไขเพื่อบอกว่ามีความแตกต่างหรือไม่ (หากสิ่งนั้นแตกต่างกันก็ทำได้มากกว่า แต่ถ้าเหมือนกันมันจะหยุดอยู่ตรงนั้น)

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

rsync -avnc $SOURCE $TARGET

( -uตัวเลือกบอก rsync ให้ข้ามไฟล์ที่ใหม่$TARGETกว่า$SOURCEซึ่งคุณอาจไม่ต้องการถ้าคุณเปรียบเทียบเนื้อหา)


6
หากคุณสนใจว่าข้อมูลเหมือนกันคุณอาจต้องการเพิ่ม--no-group --no-owner --no-perms --no-timesหรือผสมผสานสิ่งเหล่านี้ตามความต้องการของคุณ
flungo

1
@flungo หรือเพียงแค่ใช้ชุดย่อยของตัวเลือกโดยนัยโดย-aแทน-aเช่นrsync -rlDcnv --delete $SOURCE $TARGET
maxschlepzig

โปรดเพิ่มลง--deleteในรายการไฟล์ที่มีอยู่เฉพาะใน$TARGET
Tom Hale

25

สำหรับผู้ที่ไม่คุ้นเคยกับrsync:

rsync -rvnc --delete ${SOURCE}/ ${DEST}
  • -n: บิตที่สำคัญที่สุด - ไม่ได้เปลี่ยนแปลงอะไร;
  • -rc: เปรียบเทียบเนื้อหาเท่านั้น (มิฉะนั้นใช้-ac);
  • -v : รายการไฟล์)
  • --delete : มองหาสมมาตรไม่ใช่ความแตกต่างแบบทิศทางเดียว
  • สุดท้าย/หมายถึง "ดูภายในไดเรกทอรีและเปรียบเทียบเนื้อหากับปลายทาง"

มันจะพิมพ์rsyncเอาต์พุตปกติ

  • ด้วย<filename>หนึ่งไฟล์ต่อบรรทัดสำหรับไฟล์ "ใหม่" ทุกไฟล์${SOURCE}
  • และเป็นหนึ่งใน"ลบ <ชื่อไฟล์>"บรรทัดสำหรับแต่ละ "ใหม่" ${DEST}แฟ้มใน

  • นอกจากนี้ยังอาจพิมพ์คำเตือนบางอย่างเช่น"ข้ามไฟล์ <filename> ที่ไม่ใช่ไฟล์ปกติ"เพื่อหา symlink

PS ฉันรู้ว่ามันเป็น PS ที่แย่มาก - แต่มันเพิ่มเข้ามาอย่างเร่งด่วน อย่างไรก็ตามฉันเดิมพันอาจพบว่ามีประโยชน์


PPS อีกวิธีหนึ่งก็สามารถทำได้

find $SOURCE -type f -exec md5sum {} \; | tee source.md5
find $DEST   -type f -exec md5sum {} \; | tee dest.md5

หากชื่อไฟล์ไม่มีการขึ้นบรรทัดใหม่เราสามารถจัดเรียงทั้ง*.md5ไฟล์และdiffพวกเขาได้ (สิ่งนี้จะใช้งานได้กับไฟล์เท่านั้น แต่นั่นคือไดเรกทอรีว่างทั้งสองข้างจะไม่ถูกตรวจพบ)


15

น่าแปลกที่ไม่มีคำตอบใน 6 ปีที่ใช้-iตัวเลือกหรือให้ผลลัพธ์ที่ดีดังนั้นที่นี่ฉันจะไป:

TLDR - เพียงแค่แสดงคำสั่ง

rsync -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L             /'
rsync -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R             /'
rsync -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'

ทำความเข้าใจเกี่ยวกับผลลัพธ์

นี่คือตัวอย่างของผลลัพธ์:

L             file-only-in-Left-dir
R             file-only-in-right-dir
X >f.st...... file-with-dif-size-and-time
X .f...p..... file-with-dif-perms

บันทึกอักขระตัวแรกของทุกบรรทัด:

  • L/ Rหมายความว่าไฟล์ / dir ปรากฏที่Left หรือRight dir เท่านั้น
  • Xหมายความว่าไฟล์จะปรากฏบนทั้งสองข้าง แต่ไม่เหมือนกัน (ซึ่งในกรณีที่ 11 ตัวต่อไปให้ข้อมูลเพิ่มเติม. s, tและpแสดงให้เห็นถึงความแตกต่างในs ize, เสื้อ IME และพี ermissions ลำดับ - สำหรับข้อมูลเพิ่มเติมลองman rsyncและค้นหา--itemize-changes) .

ตัวเลือกพิเศษที่คุณอาจต้องการใช้

หากคุณต้องการเปรียบเทียบเจ้าของ / กลุ่ม / สิทธิ์ของไฟล์ให้เพิ่มตัวเลือก-o/ -g/ -pตามลำดับ สุดท้ายโปรดทราบว่าโดยค่าเริ่มต้น rsync จะพิจารณาไฟล์สองไฟล์เหมือนกันหากไฟล์นั้นมีชื่อเวลาและขนาดเท่ากัน สิ่งนี้เร็วมากและส่วนใหญ่เกินพอ แต่ถ้าคุณต้องการให้แน่ใจ 100% ให้เพิ่ม-cเพื่อเปรียบเทียบเนื้อหาของไฟล์ด้วยชื่อเวลาและขนาดเดียวกัน

TLDR - เพียงแค่ให้สคริปต์โทรหาฉัน

นี่มันคือ เรียกว่าเป็นแบบนี้

diff-dirs Left_Dir Right_Dir [options]

ตัวเลือกทั้งหมดที่กล่าวถึงข้างต้นในหัวข้อ "ตัวเลือกเพิ่มเติมที่คุณอาจต้องการใช้" ก็ใช้ที่นี่เช่นกัน

#!/bin/bash
# Compare two directories using rsync and print the differences
# CAUTION: options MUST appear after the directories
#
# SYNTAX
#---------
# diff-dirs Left_Dir Right_Dir [options]
#
# EXAMPLE OF OUTPUT
#------------------
# L             file-only-in-Left-dir
# R             file-only-in-right-dir
# X >f.st...... file-with-dif-size-and-time
# X .f...p..... file-with-dif-perms
#
# L / R mean that the file/dir appears only at the `L`eft or `R`ight dir. 
#
# X     means that a file appears on both sides but is not the same (in which
#       case the next 11 characters give you more info. In most cases knowing
#       that s,t,T and p depict differences in Size, Time and Permissions 
#       is enough but `man rsync` has more info
#       (look at the --itemize-changes option)
#
# OPTIONS
#---------
# All options are passed to rsync. Here are the most useful for the purpose
# of directory comparisons:
#
# -c will force comparison of file contents (otherwise only
#    time & size is compared which is much faster)
#
# -p/-o/-g will force comparison of permissions/owner/group

if [[ -z $2 ]] ; then
    echo "USAGE: $0 dir1 dir2 [optional rsync arguments]"
    exit 1
fi

set -e

LEFT_DIR=$1; shift
RIGHT_DIR=$1; shift
OPTIONS="$*"

# Files that don't exist in Right_Dir
rsync $OPTIONS -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L             /'
# Files that don't exist in Left_Dir
rsync $OPTIONS -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R             /'
# Files that exist in both dirs but have differences
rsync $OPTIONS -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'

มันทำงานยังไง?

เรากำลังเรียก rsync เช่นนี้:

rsync -rin ...

เราใช้-i( --itemize-changes) เพื่อบอก rsync ให้พิมพ์ผลลัพธ์หนึ่งบรรทัดสำหรับทุกไฟล์ที่มีข้อมูลเกี่ยวกับความแตกต่างระหว่างสองไดเรกทอรี เราจำเป็นต้อง-nหยุดพฤติกรรมปกติของ rsync (ซึ่งพยายามซิงค์ทั้งสอง dirs โดยการคัดลอก / ลบไฟล์) นอกจากนี้เรายังต้อง-rทำงานซ้ำสำหรับไฟล์ / ย่อยทั้งหมด

เราเรียก rsync สามครั้ง:

การโทรครั้งที่ 1 : พิมพ์ไฟล์ที่ไม่มีอยู่ใน Dir_B เราจำเป็นต้องใช้--ignore-existingเพื่อละเว้นไฟล์ที่มีอยู่ทั้งสองด้าน

rsync -rin --ignore-existing $DIR_A/ $DIR_B/

การโทรครั้งที่สอง : เหมือนเดิมก่อนหน้านี้ แต่เราสลับคำสั่งของ DIR_A / DIR_B

การโทรครั้งที่ 3 : ในที่สุดเราใช้--existingเพื่อตรวจสอบไฟล์ที่ปรากฏในทั้งคู่

rsync -rin --existing $DIR_A/ $DIR_B/

ไม่ทราบเกี่ยวกับผู้อื่น แต่ฉันใช้สคริปต์ของคุณ การทำงานที่ดี! ขอบคุณ
Marinaio

7

ฉันเข้าใจจากคำถามของคุณว่าคุณไม่ต้องการใช้ diff บน lsแต่คุณยังสามารถใช้ diff ซ้ำในไดเรกทอรี:

diff -rq DIR1 DIR2

2

ฉันต้องพยายามสองสามครั้งเพื่อให้เรื่องนี้ทำงาน คำตอบของนิลส์นั้นจะต้อง$TARGETลงท้ายด้วยการลากตาม/ที่อธิบายโดยジョージ

นี่คือรุ่นที่เพิ่มการติดตามอย่างชัดเจน/:

rsync -avun --delete ${TARGET}/ ${SOURCE}  | sed -ne 's/^deleting *//p'

นี่เป็นรายการไฟล์ที่มีอยู่ใต้${SOURCE}ไดเรกทอรี แต่ไม่อยู่ใต้${TARGET}ไดเรกทอรี

ฉันใช้sedที่นี่เพื่อลบผู้นำdeletingจากบรรทัดเอาท์พุทและพิมพ์เฉพาะบรรทัดเหล่านั้น

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

ฉันยังใช้-uและ-a(แทนที่จะ-r) เพื่อให้ฉันสามารถใช้บรรทัดคำสั่งใหม่ในภายหลังและเปลี่ยนเพื่อคัดลอกไดเรกทอรีและไฟล์ที่เลือกจาก${SOURCE}ไป${TARGET}เป็นดังนี้:

rsync -avu ${SOURCE}/{dirA,dirB,fileX} ${TARGET}   # copy some files

0

ฉันมีความคิดอื่นในการทำเช่นนี้:

rsync -rn --out-format=FILEDETAIL::%n  $TARGET $SOURCE  | grep "^FILEDETAIL"

คุณสามารถจับคู่ "FILEDETAIL ::" กับผลลัพธ์ของคำสั่ง นอกจากนี้คุณยังสามารถเปลี่ยนสตริง "FILEDETAIL ::" "% n" เป็นชื่อไฟล์

-r นี้จะบอก rsync เพื่อคัดลอกไดเรกทอรีซ้ำ

-n นี่ทำให้ rsync ทำการทดลองใช้ที่ไม่ได้ทำการเปลี่ยนแปลงใด ๆ

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