Очень часто возникают ситуации, когда необходимо сравнить содержимое двух или нескольких текстовых файлов. Например, для системных администраторов важно знать о конкретных различиях в конфигурации обслуживаемых систем. Программистам и разработчикам не менее важно быстро выявить различия в коде проектов, а также быстро создать патч, отражающий соответствующие изменения между двумя файлами или разными версиями одного. Это лишь самый распространённый перечень ситуаций, когда использование специализированных утилит для сравнения содержимого файлов приходится очень кстати и экономит кучу времени. Одной из таких утилит в системах Linux является diff – о ней и пойдёт речь в данной статье.
Основные возможности утилиты diff
Главное и, наверное, самое ценное преимущество diff в том, что эта утилита прекрасно работает через интерфейс командной строки. Вот почему она довольно популярна среди системных администраторов. Однако, это обстоятельство вполне закономерно объясняет и имеющийся у diff недостаток — работа с ней недостаточно наглядна, а для новичков довольно сложна.
В отличие от других аналогичных утилит, которые можно использовать исключительно в графической среде, diff прекрасно справляется со своими задачами в командной оболочке. Ну а некоторые неудобства, связанные с восприятием выводимых результатов работы утилиты — это в большинстве случаев, всего лишь недостаток пользовательского опыта работы как в командной оболочке, так и с самой утилитой diff. Стоит ещё раз отметить, что порог вхождения у неё для новичков действительно, довольно высок.
Утилита diff принимает на вход имена файлов, которые необходимо построчно сравнить, а также набор опций, управляющих режимами работы самой утилиты. В официальном руководстве (доступном по команде man diff) можно получить информацию о всех доступных для diff опциях. В данной же статье описываются лишь основные и часто используемые опции, а также простые и наглядные приёмы использования программы.
Синтаксис команды diff и её основные опции
Правила использования утилиты diff задаются командой, имеющей следующий синтаксис:
diff [OPTION] . . . [FILES]
Здесь в качестве [FILES] задаются через пробел имена файлов для сравнения. [OPTION] определяет опции работы команды, основные из которых приведены в следующей таблице:
Опция | Значение |
-q, —brief | Выводит только различия файлов. |
-s | Выводит различия только при полном совпадении файлов. |
-c, -C | Выводит количество совпадающих строк. |
-u, -U | Выводит количество отличающихся строк. |
-y, —side-by-side | Выводит содержимое в столбцах для сравнения «бок о бок». |
-l, —paginate | Постраничный вывод с поддержкой перелистывания. |
-r, —recursive | Рекурсивное сравнение всех файлов в подкаталогах. |
-i, —ignore-case | Игнорировать регистр символов. |
-b, —ignore-space-change | Игнорировать изменения в изменении пробелов. |
-w, —ignore-all-space | Игнорировать все пробелы. |
-B, —ignore-blank-lines | Игнорировать пустые строки. |
-Z, —ignore-trailing-space | Игнорировать пробелы в конце строк. |
Перед тем, как использовать утилиту diff на практике, нужно разобраться с форматом вывода результатов сравнения. Вывод команды diff представляет собой последовательность инструкций, которые необходимо выполнить, чтобы файлы стали идентичными. Эти инструкции строятся на следующих обозначениях:
- a – добавление строки;
- d – удаление строки;
- c – изменение строки.
Вывод, например, может быть таким:
2c2 < line2 --- > line22
Здесь запись «2c2» означает, что вторая строка в файле №1 (оригинал) отличается от соответствующей (второй) строки в файле №2. Символ «<» означает, что следующая за ним запись принадлежит строке из файла №1. А строка, следующая за символом «>» — файлу №2. Запись «—» чисто косметическая и предназначена для визуальной удобочитаемости результатов. Для наглядности, данный вывод соответствует результату сравнения двух файлов (file1 и file2) со следующим содержимым:
file1:
line1 line2 line3
file2:
line1 line22 line3
Использование команды diff
Теперь, для более наглядной демонстрации работы утилиты diff можно несколько усложнить условия задачи из предыдущей главы, изменив файл №2 следующим образом:
line1 line11 line22 line3 line4 line5
Тогда, выполнив команду
diff file1 file2
будет получен следующий вывод:
2c2,3 < line2 --- > line11 > line22 3a5,6 > line4 > line5
Здесь выражение «2c2,3» говорит о том, что второй строке (line2) в файле file1 соответствуют изменения в file2 в виде строк «line11» и «line22». Запись «2,3» означает диапазон строк в file2, содержащих изменения относительно строки №2 в file1. Запись «3c5,6» говорит о том, что после строки №3 оригинального файла в его изменённой версии (file2) были добавлены строки № 5 и №6, т. е. «line4» и «line5».
Создание патчей (заплаток) с помощью утилиты diff
Одной из особенностей diff является использование опции «-u» для создания патчей. Которые могут быть использованы для приведения содержимого файла к актуальному состоянию. Это очень удобно, ведь все инструкции для актуализации содержатся в одном файле-патче, который может быть обработан автоматически с помощью специализированной утилиты, например patch. Вывод для примера из предыдущей главы с использованием опции «-u» будет следующим:
$ diff -u file1 file2 --- file1 2019-04-08 20:11:51.051674991 +0400 +++ file2 2019-04-08 20:11:39.059202352 +0400 @@ -1,3 +1,6 @@ line -line2 +line11 +line22 line3 +line4 +line5
Заключение
В заключение следует отметить, что использование утилиты diff вручную в командной оболочке довольно трудоёмко, неудобно и ненаглядно. Но в данном случае важно, что задачи по сравнению файлов могут быть в принципе выполнены. В настоящее время утилита diff используется для построения вокруг неё программных обёрток с графическим пользовательским интерфейсом (подобно kompare, diffmerge и т. д.), что и позволяет использовать её с максимальной эффективностью.