rsync порівняти каталоги?


63

Чи можна порівняти два каталоги з rsync і тільки друкувати відмінності? Існує параметр "сухого виконання", але коли я збільшую багатослівність до певного рівня, відображається кожен порівняний файл.

ls -alRі diffтут немає жодного варіанту, оскільки в джерелі є жорсткі посилання, що роблять кожен рядок різним. (Звичайно, я можу видалити цю колонку за допомогою perl.)


Відповіді:


46

Вам, можливо, доведеться запускати щось на кшталт rsync -avun --deleteобох напрямків.

Але що ви насправді намагаєтесь зробити?

Оновлення :

rsync -avun --delete $TARGET $SOURCE |grep "^deleting " надасть вам список файлів, яких немає в цільовому каталозі.

"Grep Delet" , тому що кожен рядок виводить: Delet ING ..file ..

rsync -avun $SOURCE $TARGET надасть вам список "різних" файлів (включаючи нові файли).


49

Щоб додати відповідь Нілса (для тих, хто стикається з цим через 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
Том Хейл,

25

Просто для тих, хто менш знайомий rsync:

rsync -rvnc --delete ${SOURCE}/ ${DEST}
  • -n: найголовніший біт - нічого не змінювати;
  • -rc: порівнюйте лише вміст (в іншому випадку використовуйте -ac);
  • -v : список файлів)
  • --delete : шукайте симетричну, а не однонаправлену різницю.
  • Нарешті, /означає «загляньте всередину каталогу та порівняйте його вміст із пунктом призначення».

Він надрукує звичайний rsyncвихід,

  • з одним <ім'ям файлу> у рядку для кожного "нового" файлу в${SOURCE}
  • і один рядок "видалення <ім'я файла>" для кожного "нового" файлу в ${DEST}.

  • Він також може надрукувати кілька попереджень, наприклад "пропуск нестандартного файлу <ім'я файлу>" для символьних посилань.

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 або Rdright dir.
  • Xозначає , що з обох сторін з'являється файл , але це не те ж саме (в цьому випадку такі 11 символів дати вам більше інформації. s, tі pпоказують відмінності в и Ізі, т 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 (тобто спробувати синхронізувати два режими, копіюючи / видаляючи файли). нам також потрібно -rпрацювати рекурсивно для всіх файлів / підкаталів.

Ми називаємо rsync тричі:

1-й виклик : друкуйте файли, які не існують у Dir_B. Нам потрібно використовувати, --ignore-existingщоб ігнорувати файли, які існують з обох сторін.

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

2-й дзвінок : Так само, як і раніше, але ми змінюємо порядок DIR_A / DIR_B.

3-й дзвінок : Нарешті ми використовуємо --existingлише для перевірки файлів, які відображаються в обох редакціях.

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

Не знаю про інших, але я використовую ваш сценарій. Чудова робота! спасибі
Маріойо

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 виконувати пробний запуск, який не вносить жодних змін.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.