В мире Linux широко используется пара программ diff и patch. diff создает файл, в который записываются различия между 2 файлами или 2 каталогами (т.н. патч), а patch позволяет "наложить" этот патч, т.е. имея патч и один из двух файлов (каталогов), получить другой. Основное применение этих программ - создание, распространение и применение патчей к исходным текстам программ. Например, я нашел ошибку в к.-л. программе и после изучения ее исходного кода понял, что для исправления этой ошибки надо добавить 2 строчки, а еще в одной поменять несколько символов. Я хочу сообщить разработчику об этом, но каким образом указать ему на требуемые изменения? Можно это сделать обычным языком, но гораздо лучше (и удобнее для нас обоих) сделать патч и выслать его разработчику.
Или другой пример. Ядро Linux, упакованное в .tar.bz2, весит более 30 Мб независимо от его версии. Но файл различий между версиями 2.6.6 и 2.6.7, упакованный в .bz2, весит всего 3 Мб, поэтому для получения исходников ядра 2.6.7 из исходников ядра 2.6.6 достаточно скачать лишь 3 Мб, не выкачивая все 32 Мб заново.
Впрочем, часто нужно просто посмотреть различия 2 почти одинаковых файлов, и для этого тоже удобно использовать diff, выводя результат его работы не в файл, а прямо на экран.
А теперь посмотрим работу этих утилит на практике. Возьмите какой-нибудь текстовый файл и сделайте его копию, а затем отредактируйте эту копию - 1-2 строчки удалите, что-нибудь добавьте, пару строчек просто поменяйте. Затем запустите diff старый_файл новый_файл. Получите файл различий в обычном формате. В нем выводятся только измененные строки, и изменения помечены символами < и > (означающими, что соответствующая строка принадлежит левому или правому файлу в командной строке). Этот формат пригоден только для изучения человеком небольших различий между 2 файлами. Для создания патчей используются другие форматы вывода, задаваемые дополнительными опциями, при этом результат работы diff перенаправляется в файл патча стандартными средствами оболочки.
Добавьте к строке вызова diff ключ -u. Теперь вывод программы будет представлять собой патч в унифицированном формате, который используется в большинстве случаев (есть еще контекстный формат, включаемый ключом -c, но он используется намного реже). В такой патч включаются и несколько соседних неизмененных строк (т.н. контекст), помогающие программе patch найти место в файле, где произошло изменение. Добавленные во 2-м файле строки помечаются плюсами, удаленные - минусами. Если строка изменилась, она выводится 2 раза - старый вариант с минусом и новый с плюсом. Кроме того, в начале добавляется заголовок, в котором указываются имена и даты изменения обоих файлов.
diff позволяет получить различия между двумя каталогами. Это используется, как правило, чтобы получить общий патч ко всему дереву исходников программы, если было изменено несколько файлов. Для этого используются ключи -urN, а вместо 2 файлов указываются имена 2 каталогов (старого и измененного). При этом корректно обрабатываются ситуации с созданными/удаленными файлами (файл, отсутствующий в одном из каталогов, считается существующим и пустым).
Чтобы наложить патч, надо перейти в каталог, где находится старый файл/каталог, и выполнить команду
patch < файл_патча
При использовании патчей к каталогам обычно делают так: патч создается, как описано выше (тогда в заголовках патчей к отдельным файлам путь к ним будет начинаться с имени нового каталога), а прикладывается он внутри изменяемого каталога. Тогда команда будет выглядеть так:
patch -p1 < файл_патча
Здесь -p1 означает, что из заголовков патча надо убрать начальный каталог. Поясню всё это на примере. У нас имеется дерево исходников ядра 2.6.0. Это каталог linux-2.6.0, в котором содержатся каталоги drivers, arch и т.д. И у нас есть патч до версии 2.6.1, в котором содержатся такие заголовки:
--- a/drivers/acpi/Kconfig Thu Jan 8 23:00:24 2004
+++ b/drivers/acpi/Kconfig Thu Jan 8 23:00:24 2004
Видим, что при создании патча старый и новый каталоги назывались a и b соответственно. У нас же каталог называется по-другому, и patch ничего сделать не сможет. Поэтому заходим в каталог linux-2.6.0 и выполняем указанную выше команду. Теперь заголовки будут интерпретироваться как
--- drivers/acpi/Kconfig Thu Jan 8 23:00:24 2004
+++ drivers/acpi/Kconfig Thu Jan 8 23:00:24 2004
и патч приложится нормально.
(c) knoppix.ru