Назад | Перейти на главную страницу

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

Запуская 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 /

Используйте --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 scope.

Этот небольшой скрипт должен работать:

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. Надеюсь, поможет.

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.

РЕДАКТИРОВАТЬ: Я должен отметить, что кузнецответ, несомненно, лучше, но я хотел попробовать сделать это с вашим оригинальным rsync команда тактично, так как она давала вам желаемый результат.