сравнить 2 каталога и скопировать различия в 3-й каталог

32

Запустив ubuntu 12.04, я хочу сравнить 2 директории, скажем folder1 / и folder2 /, и скопировать любые файлы, отличные от folder3 /. Есть также вложенные файлы, поэтому соответствующие подкаталоги также должны быть скопированы

Есть ли одна команда, которая поможет мне? Я могу получить полный список запущенных измененных файлов:

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

Но у rsync, похоже, нет возможности «экспортировать» эти файлы в другой целевой каталог. Могу ли я передать список в cp или какую-нибудь другую программу, чтобы файлы копировались, а каталоги тоже создавались? Например, я пытался

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

но это также не сохранит каталоги, просто скопирует все файлы в folder3 /

Periklis
источник
Вероятно, я бы использовал некоторую комбинацию diff -qrи awkдля составления списка, тогда rsync...
ewwhite
как бы я использовал rsync со списком?
Периклис
Я бы либо запустил цикл for, либо использовал бы rsync --include-from=FILEопцию.
Ewwhite
(не ленитесь ...) Решение rsync ниже элегантно.
Ewwhite

Ответы:

38

Используйте --compare-dest.

Со страницы руководства:

--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-destparam.
Евгений Смирнов
4
Для меня --compare-destнеобходим абсолютный путь.
Palswim
Не работал для меня ни с опциями автора или ОП. Т.е. выводит fonts/Makefile.inфайл, который идентичен как по каталогу, так folder2и по folder1каталогу.
Привет, Ангел,
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 был бы лучшим решением, потому что он дает вам путь и имя для каждого файла последовательно.

РЕДАКТИРОВАТЬ

Это будет одна команда, ваша команда слегка изменена. Но это создаст folder1под folder3. И он не работает с полными путями, но и скрипт выше не работает с полными путями.

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

Я использовал \"в , rsyncчтобы заставить его работать с файлами и каталогами , содержащие пробелы. Проверено на Ubuntu 10.04. Надеюсь, это поможет.

Laurentiu Roescu
источник
спасибо за это, я надеялся, что хотя бы одна команда будет существовать
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/./{}extra ./используется для указания rsync на создание относительных каталогов, начиная с ./{}игнорирования folder1/. Другими словами, это избегает создания folder3/folder1/.

Я смог проверить это только на CentOS 6.4, но AFAIK должен работать так же, как в Ubuntu 12.04.

EDIT: Я хотел бы отметить , что смитовский ответ «s, несомненно , лучше, но я хотел , чтобы принять удар на это делать с оригинальной rsyncкомандой в такте , так как она дает вам желаемый результат.

s.co.tt
источник