rsync so sánh thư mục?


63

Có thể so sánh hai thư mục với rsync và chỉ in sự khác biệt? Có một tùy chọn chạy khô, nhưng khi tôi tăng mức độ chi tiết đến một mức nhất định, mọi tệp được so sánh sẽ được hiển thị.

ls -alRdiffkhông có tùy chọn nào ở đây, vì có các liên kết cứng trong nguồn làm cho mỗi dòng khác nhau. (Tất nhiên, tôi có thể xóa cột này bằng perl.)


Câu trả lời:


46

Bạn có thể sẽ phải chạy một cái gì đó giống như rsync -avun --deleteở cả hai hướng.

Nhưng những gì bạn đang thực sự cố gắng để đạt được?

Cập nhật :

rsync -avun --delete $TARGET $SOURCE |grep "^deleting " sẽ cung cấp cho bạn một danh sách các tệp không tồn tại trong thư mục đích.

"delet grep" vì mỗi dòng in: delet ing ..file ..

rsync -avun $SOURCE $TARGET sẽ cung cấp cho bạn một danh sách các tệp "khác nhau" (bao gồm các tệp mới).


49

Để thêm vào câu trả lời của Nils (cho bất kỳ ai gặp phải điều này thông qua Google), theo mặc định, rsyncchỉ so sánh kích thước tệp và thời gian sửa đổi để biết liệu có sự khác biệt nào không. (Nếu những cái đó khác nhau thì nó làm được nhiều hơn, nhưng nếu chúng giống nhau, nó dừng ở đó.)

Nếu bạn muốn so sánh nội dung tệp thực tế , ngay cả đối với các tệp có cùng kích thước và thời gian sửa đổi lần cuối, hãy thêm cờ -cđể báo rsyncđể so sánh các tệp bằng tổng kiểm tra.

rsync -avnc $SOURCE $TARGET

( -uTùy chọn yêu cầu rsync bỏ qua các tệp mới $TARGEThơn so với trên $SOURCE, mà bạn có thể không muốn nếu bạn so sánh nội dung.)


6
Nếu bạn chỉ quan tâm rằng dữ liệu giống như bạn có thể muốn thêm --no-group --no-owner --no-perms --no-timeshoặc kết hợp một số dữ liệu này dựa trên nhu cầu của bạn.
flungo

1
@flungo, hoặc chỉ sử dụng một tập hợp con của các tùy chọn bao hàm bởi -athay vì -a, ví dụ:rsync -rlDcnv --delete $SOURCE $TARGET
maxschlepzig

Vui lòng thêm --deletevào danh sách các tệp chỉ tồn tại trong$TARGET
Tom Hale

25

Chỉ dành cho những người ít quen thuộc với rsync:

rsync -rvnc --delete ${SOURCE}/ ${DEST}
  • -n: bit quan trọng nhất - không thay đổi bất cứ điều gì;
  • -rc: chỉ so sánh các nội dung (sử dụng khác -ac);
  • -v : liệt kê các tập tin)
  • --delete : tìm kiếm một sự khác biệt đối xứng, không phải là một sự khác biệt định hướng.
  • Cuối cùng, /có nghĩa là "nhìn vào bên trong thư mục và so sánh nội dung của nó với đích".

Nó sẽ in một rsyncđầu ra thông thường ,

  • với một <tên tệp> trên một dòng cho mỗi tệp "mới" trong${SOURCE}
  • và một dòng "xóa <tên tệp>" cho mỗi tệp "mới" trong ${DEST}.

  • Nó cũng có thể in một vài cảnh báo, như "bỏ qua tệp không thường xuyên <tên tệp>" cho các liên kết tượng trưng.

Tái bút Tôi biết đó là một PS khủng khiếp - nhưng nó thực sự đã được thêm vào một cách vội vàng. Tuy nhiên, tôi cá là người ta có thể thấy điều này hữu ích.


PPS. Ngoài ra, người ta cũng có thể làm

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

Nếu tên tệp không chứa dòng mới, thì chúng ta có thể sắp xếp cả hai *.md5tệp và diffchúng. (Tuy nhiên, điều này sẽ chỉ hoạt động đối với các tệp; nghĩa là, một thư mục trống ở hai bên sẽ không bị phát hiện.)


15

Đáng ngạc nhiên là không có câu trả lời nào trong 6 năm sử dụng -itùy chọn hoặc cho đầu ra tốt đẹp nên tôi sẽ đi đây:

TLDR - Chỉ cho tôi thấy các lệnh

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

Hiểu đầu ra

Đây là một ví dụ về đầu ra:

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ưu ý ký tự đầu tiên của mỗi dòng:

  • L/ Rcó nghĩa là tệp / dir chỉ xuất hiện ở thư mục Left hoặc Right.
  • Xcó nghĩa là các tập tin xuất hiện trên cả hai mặt nhưng là không giống nhau (trong trường hợp này 11 ký tự tiếp theo cung cấp cho bạn thêm thông tin. s, tpmiêu tả sự khác biệt trong s ize, t ime và p ermissions tương ứng - để biết thêm cố gắng man rsyncvà tìm kiếm --itemize-changes) .

Tùy chọn bổ sung bạn có thể muốn sử dụng

Nếu bạn cũng muốn so sánh chủ sở hữu / nhóm / quyền của các tệp, hãy thêm các tùy chọn -o/ -g/ -ptương ứng. Cuối cùng lưu ý rằng theo mặc định, rsync coi hai tệp giống nhau nếu chúng có cùng tên, thời gian và kích thước. Điều này cực kỳ nhanh và hầu hết thời gian là quá đủ nhưng nếu bạn muốn chắc chắn 100% hãy thêm -cvào để so sánh nội dung của các tệp có cùng tên, thời gian & kích thước.

TLDR - Chỉ cần cho tôi một kịch bản để gọi

Nó đây rồi Gọi nó như thế này

diff-dirs Left_Dir Right_Dir [options]

Tất cả các tùy chọn được đề cập ở trên trong phần "Tùy chọn bổ sung bạn có thể muốn sử dụng" cũng được áp dụng tại đây.

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

Làm thế nào nó hoạt động?

Chúng tôi đang gọi rsync như thế này:

rsync -rin ...

Chúng tôi sử dụng -i( --itemize-changes) để yêu cầu rsync in một dòng đầu ra cho mỗi tệp chứa thông tin về bất kỳ sự khác biệt nào giữa hai thư mục. Chúng ta cần -nloại bỏ hành vi bình thường của rsync (nghĩa là cố gắng đồng bộ hóa hai thư mục bằng cách sao chép / xóa tệp). chúng ta cũng cần -rlàm việc đệ quy cho tất cả các tệp / thư mục con.

Chúng tôi gọi rsync ba lần:

Cuộc gọi đầu tiên : in các tệp không tồn tại trong Dir_B. Chúng ta cần sử dụng --ignore-existingđể bỏ qua các tập tin tồn tại ở cả hai bên.

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

Cuộc gọi thứ 2 : Chính xác như trước nhưng chúng tôi trao đổi thứ tự của DIR_A / DIR_B.

Cuộc gọi thứ 3 : Cuối cùng, chúng tôi sử dụng --existingđể chỉ kiểm tra các tệp xuất hiện trong cả hai thư mục.

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

Không biết về người khác, nhưng tôi đang sử dụng kịch bản của bạn. Công việc tuyệt vời cảm ơn
Marinaio

7

Tôi hiểu từ câu hỏi của bạn rằng bạn không muốn sử dụng diff trên ls , nhưng bạn cũng có thể sử dụng diff đệ quy trên các thư mục:

diff -rq DIR1 DIR2

2

Tôi phải mất một vài lần để làm việc này. Câu trả lời của Nils yêu cầu $TARGETkết thúc bằng dấu /, như được giải thích bởi ジ ョ.

Đây là một phiên bản có thêm dấu vết rõ ràng /:

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

Điều này đưa ra danh sách các tập tin tồn tại bên dưới ${SOURCE}thư mục nhưng không bên dưới ${TARGET}thư mục.

Tôi sử dụng sedở đây để loại bỏ hàng đầu deletingkhỏi các dòng đầu ra và chỉ in những dòng đó.

Tôi không sử dụng rsynctùy chọn này -cvì việc so sánh nội dung tệp sẽ chậm hơn nhiều đối với các trường hợp sử dụng của tôi và chỉ so sánh kích thước tệp và thời gian sửa đổi cũng có vẻ đủ trong các trường hợp này. Tôi không có lý do để nghi ngờ rằng các máy tính của tôi gặp phải vấn đề lệch đồng hồ hoặc một cái gì đó độc hại thay đổi dấu thời gian. Ngoài ra, kết quả của việc -ckhông thể thay đổi quyết định xóa một tệp, chỉ có quyết định cập nhật hoặc giữ một tệp.

Tôi cũng sử dụng -u-a(chứ không phải -r), để sau này tôi có thể sử dụng lại dòng lệnh và thay đổi nó để sao chép các thư mục và tệp đã chọn từ ${SOURCE}sang ${TARGET}, như thế này:

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

0

Tôi có một ý tưởng khác để làm điều này:

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

Bạn có thể khớp "FILEDETAIL ::" với đầu ra của lệnh. Ngoài ra, bạn có thể thay đổi chuỗi "FILEDETAIL ::". "% N" là tên tệp.

-r Điều này nói với rsync để sao chép thư mục đệ quy.

-n Điều này làm cho rsync thực hiện chạy thử mà không thực hiện bất kỳ thay đổi nào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.