Различие двух деревьев каталогов для создания патча на уровне файлов / папок (включая двоичные файлы) - PullRequest
6 голосов
/ 22 сентября 2011

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

Ранее мы использовали хак:

fdupes -qrf newversion/ oldversion/ | grep "newversion" | xargs rm;

Оставив нам папку «newversion», которая может быть упакована как патч.

К сожалению, это оказалось катастрофическим, потому что fdupes не учитывает имена файлов.

Что было бы замечательно, так это что-то вроде fdupes, которое действительно включало имя файла в сравнение.

Ответы [ 3 ]

5 голосов
/ 22 сентября 2011

Команда diff может быть запрошена для вывода имен файлов, которые отличаются.

diff --quiet --recurse --unidirectional-new-file OLDDIR NEWDIR

Files old/main and new/main differ
Files old/main.cpp and new/main.cpp differ
Files old/Makefile and new/Makefile differ
Files old/sounds/popalien.wav and new/sounds/popalien.wav differ
Files old/sounds/saucer.wav and new/sounds/saucer.wav differ

Конечно, это не очень приятный вывод, но, поскольку вы ищете только НОВЫЕ файлы, которые нужно упаковать как патч, быстрый конвейер sed творит чудеса:

diff --quiet --recurse -unidirectional-new-file OLDDIR NEWDIR | \
  sed "s/^.* and \(.*\) differ/\1/"

(не читается для читабельности)

new/main
new/main.cpp
new/Makefile
new/sounds/popalien.wav
new/sounds/saucer.wav

Пробелы вокруг 'и' и предшествующие 'отличаются'

ПОРЯДОК операндов для diff имеет значение, первый аргумент остается от 'и', второй - после. Остерегайтесь этого.

Кроме того, если вы удалите файл из NEWDIR, он не найдет его как заданный, только добавленные или измененные файлы. Чтобы также вывести имена файлов для файлов, не найденных ни в одном из подкаталогов, замените --unidirection-new-file на --new-file. (короткие опции существуют для всех, кроме --unidirectional ..)

1 голос
/ 22 сентября 2011

diff -ruN oldversion newversion

0 голосов
/ 14 января 2016

Я знаю, что это было давно.Мне нужно такое же решение.Я нашел этот пост, но этого было недостаточно.Затем я обнаружил, что rsync может выполнять работу, если вы `` исправляете`` идентичные копии, и вам не нужно объединяться с другими изменениями.Я собираюсь использовать это для обновления зеркал yum на отключенных машинах.Мое полное решение немного сложнее, и я пишу команды из памяти, поэтому некоторые мелкие детали могут быть неправильными, но в основе:

# create identical copy "copy.0"
rsync -a master/ copy.0/

# Presumably transfer copy.0/ to another machine for offline use
# but copy.0 must not mutate outside of this process or sync probably
# will not work.

# some time later update master, e.g. rsync master from upstream mirror
# mutates master in some way, changes/adds/removes remove files including
# binaries
echo -n $'\001\002' > master/new.bin
rm master/gone.bin

# generate rsync batch that can be used to ``patch`` copy.0
# to become identical to master
rsync -a --delete --itemize-changes --only-write-batch=copy.0.batch \
    master/ copy.0/
# now the file copy.0.batch contains only the deltas to be applied

# transfer the batch file to where it needs to be applied

# apply the batch to copy.0
rsync -a --delete --itemize-changes --read-batch=copy.0.batch copy.0/

Это касается удаления и многих других вещей, вероятно разрешения, метки времени и т. д., но я думаю, что он может не обрабатывать жесткие ссылки как жесткие ссылки и, вероятно, будет создавать их как отдельные несвязанные файлы.

...