Как сравнить два текстовых файла в терминале 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. Параметры, которые мы использовали в приведенных выше примерах, позволят вам отследить все различия между версиями ваших текстовых файлов, используя командную строку и человеческий глаз.
Linux Commands | ||
Files | tar · pv · cat · tac · chmod · grep · diff · sed · ar · man · pushd · popd · fsck · testdisk · seq · fd · pandoc · cd · $PATH · awk · join · jq · fold · uniq · journalctl · tail · stat · ls · fstab · echo · less · chgrp · chown · rev · look · strings · type · rename · zip · unzip · mount · umount · install · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · patch · convert · rclone · shred · srm · scp · gzip · chattr · cut · find · umask · wc | |
Processes | alias · screen · top · nice · renice · progress · strace · systemd · tmux · chsh · history · at · batch · free · which · dmesg · chfn · usermod · ps · chroot · xargs · tty · pinky · lsof · vmstat · timeout · wall · yes · kill · sleep · sudo · su · time · groupadd · usermod · groups · lshw · shutdown · reboot · halt · poweroff · passwd · lscpu · crontab · date · bg · fg · pidof · nohup · pmap | |
Networking | netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · dig · finger · nmap · ftp · curl · wget · who · whoami · w · iptables · ssh-keygen · ufw · arping · firewalld |
RELATED: Best Linux Laptops for Developers and Enthusiasts