Как сохранить измененные файлы?

8

У меня есть две папки:

  • ОРИГИНАЛ /
  • ORIGINAL_AND_MY_CHANGES /

У моего друга есть копия ОРИГИНАЛА /. Я хотел бы сгенерировать MY_CHANGES.tgz - он должен содержать только новые / измененные файлы из ORIGINAL_AND_MY_CHANGES / по сравнению с ORIGINAL /. Так что мой друг может распаковать его в свою копию ORIGINAL / и получить ORIGINAL_AND_MY_CHANGES /. Как я могу это сделать?

PS Я пытался, diffно он не может сохранить двоичные данные и rsync --link-dest- он создает жесткие ссылки, которые бесполезны в архиве.

PPS В моем случае время модификации не может быть использовано, чтобы решить, какой файл был изменен.

Дмитрий
источник
1
Вы смотрели в справочнике «diff»? вопрос?
rozcietrzewiacz

Ответы:

7

С rsync

То, что вы делаете, по сути является инкрементной резервной копией: у вашего друга (вашей резервной копии) уже есть исходные файлы, и вы хотите создать архив, содержащий файлы, которые вы изменили по сравнению с этим оригиналом.

Rsync имеет функции для инкрементного резервного копирования.

cd ORIGINAL_AND_MY_CHANGED
rsync -a -c --compare-dest=../ORIGINAL . ../CHANGES_ONLY
  • -a означает сохранить все атрибуты (время, собственность и т. д.).
  • -c означает сравнивать содержимое файла и не полагаться на дату и размер.
  • --compare-dest=/some/directoryозначает, что файлы, идентичные в этом каталоге и в исходном дереве, не копируются. Обратите внимание, что путь относительно каталога назначения.

Rsync копирует все каталоги, даже если там нет файлов. Чтобы избавиться от этих пустых каталогов, запустите find -depth CHANGES_ONLY -type d -empty -delete(или, если у вас findнет -deleteи -empty, запустите find -depth CHANGES_ONLY -exec rmdir {} + 2>/dev/null).

Затем сделайте архив из CHANGES_ONLYкаталога.

Пешеходный путь

Пройдите по каталогу с вашим файлом. Пропустить файлы, которые идентичны оригиналу. При необходимости создайте каталоги в целевой папке. Скопируйте измененные файлы.

cd ORIGINAL_AND_MY_CHANGES
find . \! -type d -exec sh -c '
  for x; do
    if cmp -s "$x" "../ORIGINAL/$x"; then continue; fi
    [ -d "../CHANGES_ONLY/$x" ] || mkdir -p "../CHANGES_ONLY/${%/*}"
    cp -p "$x" "../CHANGES_ONLY/$x"
  done
' {} +
Жиль "ТАК - перестань быть злым"
источник
Это даже лучшее решение, чем у enzotib, потому что я могу поместить MY_CHANGES в систему контроля версий и обновлять / отслеживать эти изменения (если я обновлю командный файл rsync под управлением системы контроля версий, будет невозможно увидеть, какие файлы были изменены)
Дмитрий
@Dmitry Если вы используете контроль версий, почему бы не поставить import / track ORIGINALи сделать ORIGINAL_AND_MY_CHANGESветку? Тогда узнайте CHANGESс помощью команды scm.
Жиль "ТАК - перестань быть злым"
В моем случае ORIGINALэто исходники платформы Android (3ГБ, 126000 файлов). Даже запуск rsync занимает ~ 15-20 минут. Я думаю, что добавление всего этого материала под контроль исходного кода займет слишком много места и времени.
Дмитрий
@Dmitry Это решает тогда. Если это исходники Android, используйте repo и git. Работайте на своей ветке. Управлять теми, кто управляет версией, достаточно сложно, я не могу понять, как это может быть без него. К счастью, Git очень хорошо управляет местными филиалами.
Жиль "ТАК - перестань быть злым"
К сожалению, это пользовательские исходники Android без каких-либо репозиториев repo / git.
Дмитрий
5

Команда

rsync --only-write-batch=FILE $other_options ORIGINAL_AND_MY_CHANGES/ ORIGINAL/

создаст пакетный файл, содержащий необходимые изменения (без каких-либо изменений).

Патч может быть применен на другом сайте, где вы берете пакетный файл, с

rsync --read-batch=FILE ORIGINAL/
enzotib
источник