порівняйте 2 каталоги та копіюйте відмінності у 3-му каталозі


32

Запускаючи ubuntu 12.04, я хочу порівнювати 2 каталоги, скажімо, папка1 / і папка2 / та копіювати будь-які файли, які відрізняються від папки3 /. Також є вкладені файли, тому також слід скопіювати відповідні підкаталоги

Чи є одна команда, яка б мені допомогла? Я можу отримати повний список запущених змін:

rsync -rcnC --out-format="%f" folder1/ folder2/

Але, схоже, rsync не має можливості "експортувати" ці файли в інший цільовий каталог. Чи можу я передати список на cp чи якусь іншу програму, щоб файли були скопійовані, а каталоги також створені? Наприклад, я спробував

rsync -rcnC --out-format="%f" folder1/ folder2/ | xargs cp -t folder3/

але це також не збереже каталоги, воно просто скопіює всі файли всередині папки3 /


Я, мабуть, використовував би якесь поєднання diff -qrі awkдля створення списку, тоді rsync...
ewwhite

як я можу використовувати rsync зі списком?
перикліс

Я б або запустив цикл for або використав rsync --include-from=FILEопцію.
ewwhite

(не лінуйтеся ...) Але рішення rsync нижче є елегантним.
ewwhite

Відповіді:


38

Використовувати --спорівняти-призначення.

На чоловіковій сторінці:

--compare-dest = DIR - Цей параметр дає змогу rsync використовувати DIR на машині призначення як додаткову ієрархію для порівняння файлів призначення з виконанням передач (якщо файли відсутні в каталозі призначення). Якщо в DIR-файл знайдений файл, ідентичний файлу відправника, файл НЕ буде перенесений у каталог призначення. Це корисно для створення розрідженої резервної копії лише файлів, змінених із попередньої резервної копії.

спочатку перевірте свій синтаксис за допомогою --dry-run

rsync -aHxv --progress --dry-run --compare-dest=folder2/ folder1/ folder3/

Тоді як тільки ви будете задоволені результатом:

rsync -aHxv --progress  --compare-dest=folder2/ folder1/ folder3/

це посилання має чітке пояснення сфери --compare-dest.


1
Дякую за це, я не зрозумів пояснення цього параметра на сторінці чоловічої сторінки. Для всіх, хто зацікавився, я це зробивrsync -rcC --compare-dest=folder2/ folder1/ folder3/
periklis

швидка примітка для користувачів OsX. У мене rsync version 3.1.1 protocol version 31на локальному і rsync не розуміє ~/шляхів до --compare-destпарам.
Євгеній Смірнов

4
Для мене --compare-destпотрібен абсолютний шлях.
palswim

Не працювали для мене з параметрами автора чи ОП. Тобто він виводить fonts/Makefile.inфайл, який однаковий folder2і в folder1dirs.
Привіт-Ангел

3

Цей маленький сценарій повинен працювати:

folder1="firsts_folder/"
folder2="second_folder/"
folder3="target_folder"
for x in `rsync -rcnC --out-format="%n"  $folder1 $folder2`
    do
        if [ -d "$folder1/$x" ]; then
            mkdir -p "$folder3/$x"
        else
            cp -frv $folder1/$x $folder3/$x
        fi
done

Але я також думаю, що синтаксичний розбір diff -qr був би кращим рішенням, оскільки він дає вам шлях та ім'я для кожного файлу послідовно.

EDIT

Це була б одна команда, ваша команда трохи змінена. Але це створить folder1під folder3. І це не працює з повними шляхами, але також і сценарій вище не працює з повними шляхами.

rsync -rcnC --out-format="\"%f\"" folder1/ folder2/ | xargs cp --parents -rfvt folder3/

Я використовував \"в , rsyncщоб змусити його працювати з файлами і каталогами , що містять пробіли. Тестовано на Ubuntu 10.04. Сподіваюся, це допомагає.


спасибі за це, я сподівався , що одна команда буде існувати , хоча
Periklis

2
rsync -rcnC --out-format="%f" . ../folder2/ |xargs cp --parents -rt ../folder3/

Це найпростіша форма, яку я міг би придумати, якщо ти бажаєш спершу спуститися в неї folder1 як видавати команду.

Це більш повільний варіант, але я вважаю, що він відповідає вашим вимогам, і його можна виконати, використовуючи невідповідні назви каталогів:

rsync -rcnC --out-format="%n" folder1/ folder2/ |grep -vP "/$" |xargs -I{} rsync -R folder1/./{} folder3/

Я залишив вашу оригінальну rsyncкоманду в спокої, тому що ви сказали, що вона дає вам правильний список файлів (а мої тестові файли, очевидно, відрізняються від ваших, тому я не могла напевно сказати, що отримаю правильний список файлів, якщо заблукаю з цим).

grepЄ , щоб видалити імена каталогів з виходу rsync.

Потім висновок grepпередається на інший rsyncза допомогою xargs. У парамі folder1/./{}додаткове ./використовується для того, щоб сказати rsync для створення відносних каталогів, починаючи з ./{}ігнорування folder1/. Іншими словами, це уникає створення folder3/folder1/.

Мені вдалося протестувати це лише на CentOS 6.4, але в AFAIK він повинен працювати так само в Ubuntu 12.04.

EDIT: Я мушу зазначити, що відповідь Смітфана , безперечно, краща, але я хотів зафіксувати це, виконуючи свою оригінальну rsyncкоманду в такті, оскільки вона дала вам бажаний результат.

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