Поиск по сайту:

Как сравнить два текстовых файла в терминале Linux


Нужно увидеть различия между двумя версиями текстового файла? Тогда вам нужна команда diff. В этом руководстве показано, как использовать diff в Linux и macOS простым способом.

Погружение в diff

Команда diff сравнивает два файла и выводит список различий между ними. Чтобы быть более точным, он создает список изменений, которые необходимо внести в первый файл, чтобы он соответствовал второму файлу. Если вы будете помнить об этом, вам будет легче понять вывод diff. Команда diff была разработана для поиска различий между файлами исходного кода и создания выходных данных, которые могут быть прочитаны и обработаны другими программами, такими как команда patch. В этом руководстве мы рассмотрим наиболее полезные и удобные способы использования diff.

Давайте погрузимся прямо и проанализируем два файла. Порядок файлов в командной строке определяет, какой файл diff считает «первым файлом», а какой — «вторым файлом». В приведенном ниже примере alpha1 — это первый файл, а alpha2 — второй файл. Оба файла содержат фонетический алфавит, но второй файл, alpha2, подвергся дальнейшему редактированию, так что эти два файла не идентичны.

Мы можем сравнить файлы с помощью этой команды. Введите diff, пробел, имя первого файла, пробел, имя второго файла и нажмите Enter.

diff alpha1 alpha2

Как мы анализируем этот вывод? Когда вы знаете, что искать, это не так уж плохо. Каждое различие перечисляется по очереди в одном столбце, и каждое различие помечается. Метка содержит числа по обе стороны от буквы, например 4c4. Первое число — это номер строки в alpha1, а второе число — это номер строки в alpha2. Буква в середине может быть:

  • c: строку в первом файле необходимо изменить, чтобы она соответствовала строке во втором файле.
  • d: строка в первом файле должна быть удалена, чтобы соответствовать второму файлу.
  • a: в первый файл необходимо добавить дополнительный контент, чтобы он соответствовал второму файлу.

4c4 в нашем примере говорит нам, что четвертая строка alpha1 должна быть изменена, чтобы соответствовать четвертой строке alpha2. Это первое различие между двумя файлами, найденными diff.

Строки, начинающиеся с <, относятся к первому файлу, в нашем примере alpha1, а строки, начинающиеся с >, относятся ко второму файлу, alpha2. Строка < Delta говорит нам, что слово Delta является содержимым четвертой строки в alpha1. Строка > Dave сообщает нам, что слово Dave является содержимым четвертой строки в alpha2. Подводя итог, нам нужно заменить Delta на Dave в четвертой строке в alpha1, чтобы эта строка совпадала в обоих файлах.

Следующее изменение обозначается кодом 12c12. Применяя ту же логику, это говорит нам о том, что строка 12 в alpha1 содержит слово Lima, а строка 12 в alpha2 содержит слово Linux.

Третье изменение относится к строке, которая была удалена из alpha2. Метка 21d20 расшифровывается как «строка 21 должна быть удалена из первого файла, чтобы оба файла синхронизировались, начиная со строки 20». Строка < Uniform показывает нам содержимое строки, которую нужно удалить из alpha1.

Четвертое отличие помечено 26a26,28. Это изменение относится к трем дополнительным строкам, добавленным в alpha2. Обратите внимание на 26,28 в ярлыке. Двухстрочные числа, разделенные запятой, представляют собой диапазон номеров строк. В этом примере диапазон – от строки 26 до строки 28. Ярлык интерпретируется как в строке 26 в первом файле добавьте строки с 26 по 28 из второго файла. Нам показаны три строки в alpha2, которые нужно добавить к alpha1. Они содержат слова Quirk, Strange и Charm.

Быстрые остроты

Если вы хотите узнать, являются ли два файла одинаковыми, используйте параметр -s (отчет об идентичных файлах).

diff -s alpha1 alpha3

Вы можете использовать параметр -q (brief), чтобы получить столь же краткое утверждение о двух разных файлах.

diff -q alpha1 alpha2

Следует обратить внимание на то, что с двумя идентичными файлами опция -q (brief) полностью замолкает и вообще ничего не сообщает.

Альтернативный взгляд

Параметр -y (бок о бок) использует другой макет для описания различий файлов. Часто бывает удобно использовать параметр -W (ширина) при просмотре рядом, чтобы ограничить количество отображаемых столбцов. Это позволяет избежать уродливых строк с переносом, которые затрудняют чтение вывода. Здесь мы указали diff на отображение рядом друг с другом и ограничение вывода до 70 столбцов.

diff -y -W 70 alpha1 alpha2

Первый файл в командной строке, alpha1, показан слева, а вторая строка в командной строке, alpha2, показана справа. Строки из каждого файла отображаются рядом. Рядом с теми строками в alpha2, которые были изменены, удалены или добавлены, есть индикаторные символы.

  • |: строка, которая была изменена во втором файле.
  • <: строка, которая была удалена из второго файла.
  • >: добавленная во второй файл строка, которой нет в первом файле.

Если вы предпочитаете более компактную сводку различий между файлами, используйте параметр --suppress-common-lines. Это заставляет diff отображать только измененные, добавленные или удаленные строки.

diff -y -W 70 --suppress-common-lines alpha1 alpha2

Добавьте всплеск цвета

Другая утилита, называемая colordiff, добавляет выделение цветом в вывод diff. Это позволяет намного легче увидеть, какие линии имеют различия.

Используйте apt-get для установки этого пакета в вашу систему, если вы используете Ubuntu или другой дистрибутив на основе Debian. В других дистрибутивах Linux вместо этого используйте инструмент управления пакетами вашего дистрибутива Linux.

sudo apt-get install colordiff

Используйте colordiff так же, как и  diff.

Фактически, colordiff является оболочкой для diff, а diff выполняет всю работу за кулисами. Поэтому все параметры diff будут работать с colordiff.

Предоставление некоторого контекста

Чтобы найти золотую середину между отображением всех строк в файлах на экране и перечислением только измененных строк, мы можем попросить diff предоставить некоторый контекст. Есть два способа сделать это. Оба способа достигают одной и той же цели: отображать несколько строк до и после каждой измененной строки. Вы сможете увидеть, что происходит в файле в том месте, где была обнаружена разница.

Первый метод использует параметр -c (скопированный контекст).

colordiff -c alpha1 alpha2

Выходные данные diff содержат заголовок. В заголовке перечислены два имени файла и время их модификации. Перед именем первого файла стоят звездочки (*), а перед именем второго файла — тире (-). Звездочки и тире будут использоваться, чтобы указать, к какому файлу принадлежат строки в выводе.

Ряд звездочек с 1,7 в середине указывает, что мы смотрим на строки из alpha1. Чтобы быть точным, мы смотрим на строки с первой по седьмую. Слово Delta помечается как измененное. Рядом с ним стоит восклицательный знак ( ! ), и он красного цвета. Перед и после этой строки отображаются три строки неизменного текста, поэтому мы можем видеть контекст этой строки в файле.

Линия штрихов с 1,7 в середине говорит нам, что мы сейчас смотрим на строки из альфа2. Опять же, мы смотрим на строки с первой по седьмую, при этом слово Dave в четвертой строке помечено как отличающееся.

Три строки контекста выше и ниже каждого изменения — это значение по умолчанию. Вы можете указать, сколько строк контекста вы хотите предоставить diff. Для этого используйте параметр -C (скопированный контекст) с заглавной «C» и укажите необходимое количество строк:

colordiff -C 2 alpha1 alpha2

Второй параметр diff, предлагающий контекст, — это параметр -u (унифицированный контекст).

colordiff -u alpha1 alpha2

Как и прежде, у нас есть заголовок на выходе. Два файла названы, и показано время их модификации. Перед названием alpha1 стоят тире (-), а перед названием alpha2 — знаки плюс (+). Это говорит нам о том, что тире будут использоваться для обозначения alpha1, а знаки плюс будут использоваться для обозначения alpha2. По всему листингу разбросаны строки, начинающиеся со знаков (@). Эти линии отмечают начало каждой разницы. Они также сообщают нам, какие строки отображаются в каждом файле.

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

Как и следовало ожидать, мы можем попросить diff предоставить именно то количество строк единого контекста, которое мы хотели бы видеть. Для этого используйте параметр -U (унифицированный контекст) с заглавной буквой «U» и укажите необходимое количество строк:

colordiff -U 2 alpha1 alpha2

Игнорирование пробелов и регистра

Давайте проанализируем еще два файла, test4 и test5. В них есть имена шести супергероев.

colordiff -y -W 70 test4 test5

Результаты показывают, что diff не находит отличий от строк Black Widow, Spider-Man и Thor. Он отмечает изменения в линиях Капитана Америки, Железного человека и Халка.

Так что же изменилось? Что ж, в test5 Халк пишется со строчной буквы «h», а у Капитана Америки есть дополнительный пробел между «Капитан» и «Америка». Хорошо, это ясно видно, но что не так с линией Ironman? Видимых различий нет. Вот хорошее практическое правило. Если вы его не видите, ответ — пустое пространство. В конце этой строки почти наверняка есть пробел или два, или символ табуляции.

Если они не имеют для вас значения, вы можете указать diff игнорировать определенные типы различий строк, в том числе:

  • -i: игнорировать различия в регистре.
  • -Z: игнорировать пробелы в конце.
  • -b: игнорировать изменения количества пробелов.
  • -w: игнорировать все изменения пробелов.

Давайте попросим diff снова проверить эти два файла, но на этот раз проигнорировать любые различия в случае.

colordiff -i -y -W 70 test4 test5

Строки с «The Hulk» и «The hulk» теперь считаются совпадением, и для строчной буквы «h» никакие различия не помечаются. Попросим diff также игнорировать пробелы в конце.

colordiff -i -Z -y -W 70 test4 test5

Как и предполагалось, конечный пробел должен был быть разницей в строке Ironman, потому что diff больше не помечает разницу для этой строки. Остается Капитан Америка. Давайте попросим diff игнорировать регистр и игнорировать все проблемы с пробелами.

colordiff -i -w -y -W 70 test4 test5

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

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

RELATED: Best Linux Laptops for Developers and Enthusiasts