rsync membandingkan direktori?


63

Apakah mungkin membandingkan dua direktori dengan rsync dan hanya mencetak perbedaannya? Ada opsi kering-lari, tetapi ketika saya meningkatkan verbositas ke tingkat tertentu, setiap file dibandingkan ditampilkan.

ls -alRdan difftidak ada pilihan di sini, karena ada hardlink di sumber yang membuat setiap baris berbeda. (Tentu saja, saya bisa menghapus kolom ini dengan perl.)


Jawaban:


46

Anda harus menjalankan sesuatu seperti rsync -avun --deletedi kedua arah.

Tetapi apa yang sebenarnya ingin Anda capai?

Perbarui :

rsync -avun --delete $TARGET $SOURCE |grep "^deleting " akan memberi Anda daftar file yang tidak ada di direktori target.

"grep delet" karena setiap baris dicetak: delet ing ..file ..

rsync -avun $SOURCE $TARGET akan memberi Anda daftar file "berbeda" (termasuk file baru).


49

Untuk menambah jawaban Nils (bagi siapa saja yang menemukan ini melalui Google), secara default rsynchanya membandingkan ukuran file dan waktu modifikasi untuk mengetahui apakah ada perbedaan. (Jika berbeda, ia lebih banyak, tetapi jika sama, ia berhenti di sana.)

Jika Anda ingin membandingkan konten file yang sebenarnya , bahkan untuk file yang memiliki ukuran yang sama dan waktu modifikasi terakhir, tambahkan tanda -cuntuk memberitahu rsyncuntuk membandingkan file menggunakan checksum.

rsync -avnc $SOURCE $TARGET

( -uOpsi memberi tahu rsync untuk mengabaikan file yang lebih baru $TARGETdaripada pada $SOURCE, yang mungkin tidak Anda inginkan jika Anda membandingkan konten.)


6
Jika Anda hanya peduli bahwa datanya sama, Anda mungkin ingin menambahkan --no-group --no-owner --no-perms --no-timesatau kombinasi keduanya berdasarkan kebutuhan Anda.
flungo

1
@ flungo, atau cukup gunakan himpunan bagian dari opsi yang disiratkan oleh -aalih-alih -a, misalnyarsync -rlDcnv --delete $SOURCE $TARGET
maxschlepzig

Harap tambahkan --deleteke daftar file yang hanya ada di$TARGET
Tom Hale

25

Hanya untuk mereka yang kurang terbiasa dengan rsync:

rsync -rvnc --delete ${SOURCE}/ ${DEST}
  • -n: Bit yang paling penting - jangan tidak mengubah apa-apa;
  • -rc: bandingkan hanya konten (jika tidak gunakan -ac);
  • -v : daftar file)
  • --delete : mencari perbedaan simetris, bukan uni-directional.
  • Akhirnya, /berarti "melihat ke dalam direktori, dan membandingkan isinya dengan tujuan".

Ini akan mencetak rsyncoutput yang biasa ,

  • dengan satu <filename> di baris untuk setiap file "baru" di${SOURCE}
  • dan satu baris "hapus <filename>" untuk setiap file "baru" di ${DEST}.

  • Ini juga dapat mencetak beberapa peringatan, seperti "melewatkan file <filename> tidak biasa" untuk symlink.

PS. Saya tahu ini adalah PS yang mengerikan - tetapi memang ditambahkan dengan terburu-buru. Namun demikian, saya yakin seseorang mungkin menemukan ini berguna.


PPS. Atau, seseorang juga bisa melakukannya

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

Jika nama file tidak mengandung baris baru, kami kemudian dapat mengurutkan kedua *.md5file, dan diffmereka. (Ini hanya akan berfungsi untuk file; artinya, direktori kosong di kedua sisi tidak akan terdeteksi.)


16

Anehnya tidak ada jawaban dalam 6 tahun menggunakan -iopsi atau memberikan output yang bagus jadi di sini saya akan pergi:

TLDR - Tunjukkan saja padaku perintahnya

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 /'

Memahami output

Berikut ini contoh outputnya:

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

Perhatikan karakter pertama dari setiap baris:

  • L/ RBerarti file / dir hanya muncul di Left atau Right dir.
  • Xberarti bahwa file tersebut muncul di kedua sisi, tapi tidak sama (dalam hal ini 11 karakter berikutnya memberikan info lebih lanjut. s, tdan pmenggambarkan perbedaan s ize, t ime dan p ermissions masing - untuk info lebih lanjut mencoba man rsyncdan mencari --itemize-changes) .

Opsi tambahan yang mungkin ingin Anda gunakan

Jika Anda ingin juga membandingkan pemilik / grup / izin file tambahkan opsi -o/ -g/ -pmasing-masing. Akhirnya perhatikan bahwa secara default rsync menganggap dua file sama jika mereka memiliki nama, waktu, dan ukuran yang sama. Ini sangat cepat dan sebagian besar kali lebih dari cukup tetapi jika Anda ingin 100% yakin tambahkan -cjuga membandingkan konten file dengan nama, waktu & ukuran yang sama.

TLDR - Beri aku skrip untuk dihubungi

Ini dia. Sebut saja seperti ini

diff-dirs Left_Dir Right_Dir [options]

Semua opsi yang disebutkan di atas di bagian "Opsi tambahan yang ingin Anda gunakan" juga berlaku di sini.

#!/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 /'

Bagaimana cara kerjanya?

Kami memanggil rsync seperti ini:

rsync -rin ...

Kami menggunakan -i( --itemize-changes) untuk memberitahu rsync untuk mencetak satu baris output untuk setiap file yang berisi informasi tentang perbedaan antara dua direktori. Kita perlu -nmenekan perilaku normal rsync (yaitu mencoba menyinkronkan kedua dir dengan menyalin / menghapus file). kita juga perlu -rbekerja secara rekursif untuk semua file / sub-dir.

Kami memanggil rsync tiga kali:

Panggilan pertama : cetak file yang tidak ada di Dir_B. Kita perlu menggunakan --ignore-existinguntuk mengabaikan file yang ada di kedua sisi.

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

Panggilan kedua : Persis seperti sebelumnya, tetapi kami menukar urutan DIR_A / DIR_B.

Panggilan ketiga : Akhirnya kami --existinghanya menggunakan untuk memeriksa file yang muncul di kedua dir.

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

Tidak tahu tentang orang lain, tetapi saya menggunakan skrip Anda. Kerja bagus! terima kasih
Marinaio

Terima kasih banyak! Saya perlu beberapa penyesuaian, akan membagikannya di bawah jika seseorang mencari sesuatu yang serupa. Pertama, saya ingin menjalankan remote rsync sebagai pengguna sudo, untuk itu saya menambahkan --rsync-path="sudo rsync"ke setiap perintah rsync. Kedua, saya ingin membandingkan direktori lokal dengan direktori jarak jauh. Saya menambahkan --rsh "ssh -p1234"karena dalam kasus saya SSH berjalan pada port 1234. Kemudian saya memanggil script like diff-dirs user@111.11.1.1:/mnt/Vol1/dir1/ /localMnt/dir1 -c.
sen4ik

7

Saya mengerti dari pertanyaan Anda bahwa Anda tidak ingin menggunakan diff pada ls , tetapi Anda juga dapat menggunakan diff secara rekursif pada direktori:

diff -rq DIR1 DIR2

2

Butuh beberapa kali saya mencoba untuk membuatnya bekerja. Jawaban Nils mensyaratkan bahwa $TARGETdiakhiri dengan trailing /, seperti dijelaskan oleh ジ ョ ー ジ.

Berikut adalah versi yang secara eksplisit menambahkan trailing /:

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

Ini memberikan daftar file yang ada di bawah ${SOURCE}direktori tetapi tidak di bawah ${TARGET}direktori.

Saya menggunakan di sedsini untuk menghapus garis depan deletingdari garis keluaran, dan hanya mencetak garis-garis itu.

Saya tidak menggunakan rsyncopsi -ckarena membandingkan konten file akan jauh lebih lambat untuk kasus penggunaan saya, dan membandingkan hanya ukuran file dan waktu modifikasi juga tampaknya cukup dalam kasus ini. Saya tidak punya alasan untuk curiga bahwa komputer saya mengalami masalah kemiringan jam atau sesuatu yang jahat mengubah perangko waktu. Juga, hasil dari -ctidak dapat mengubah keputusan untuk menghapus file, hanya keputusan untuk memperbarui atau menyimpan file.

Saya juga menggunakan -udan -a(bukan -r), sehingga nantinya saya dapat menggunakan kembali baris perintah dan mengubahnya untuk menyalin direktori dan file yang dipilih dari ${SOURCE}ke ${TARGET}, seperti ini:

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

0

Saya punya ide lain untuk melakukan ini:

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

Anda dapat mencocokkan "FILEDETAIL ::" dengan output dari perintah. Anda juga dapat mengubah string "FILEDETAIL ::". "% N" adalah nama file.

-r Ini memberitahu rsync untuk menyalin direktori secara rekursif.

-n Ini membuat rsync menjalankan percobaan yang tidak membuat perubahan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.