Битлента
Сетевые команды и утилиты6 мин чтения·

diff в терминале: как сравнить два файла и две папки

Как пользоваться diff в Linux и macOS: формат -u, ключи -q, -r, -w, чтение знаков + и -, коды возврата 0, 1, 2 и сравнение вывода двух команд.

Кратко

diff файл1 файл2 печатает различия между файлами построчно, формат -u делает их читаемыми, -q говорит только «отличаются», а -r сравнивает каталоги. Код возврата 0 означает «одинаковы», 1 — «различаются», 2 — ошибка.

Первый запуск и как прочитать результат

Допустим, у вас две версии конфигурационного файла и нужно понять, что изменилось. Глазами по длинным текстам это делать долго и ненадёжно, а diff показывает только отличающиеся строки. Для опыта создайте два небольших файла: printf 'a\nb\nc\n' > one.txt и printf 'a\nB\nc\nd\n' > two.txt. Затем выполните diff one.txt two.txt.

Классический формат вывода использует номера строк и команды вроде c (change), a (add) и d (delete): например, 2c2 говорит, что вторая строка первого файла заменена второй строкой второго. Строки со знаком «меньше» относятся к первому файлу, со знаком «больше» ко второму. Этот формат компактен, но привыкнуть к нему сложнее, чем к следующему.

Если файлы одинаковы, diff ничего не печатает. Это не сбой, а нормальный результат, и именно по молчанию вы узнаёте, что различий нет. Результат сравнения доступен и числом: после выполнения команды переменная $? хранит код возврата.

  • 0 — файлы совпадают;
  • 1 — найдены различия;
  • 2 — произошла ошибка, например файла нет или нет прав на чтение.

Эти коды позволяют использовать diff в скриптах с условиями if, не разбирая текст вывода.

Формат -u: плюсы и минусы строк

Чаще всего пользуются унифицированным форматом, который включается ключом -u. Его же ожидают многие программы для обмена правками. Запустите diff -u one.txt two.txt и посмотрите на структуру вывода.

Сначала идут две строки заголовка: имена файлов, перед первым стоят три минуса, перед вторым три плюса, рядом время изменения. Затем следуют блоки, каждый открывается строкой с символами @@ и диапазонами номеров строк. Внутри блока:

  • строка с минусом в начале есть в первом файле, но отсутствует во втором;
  • строка с плюсом появилась во втором файле;
  • строка с пробелом в начале одинакова в обоих и показана для контекста.

В нашем примере вы увидите, что строка b убрана, строка B добавлена, а строка d добавлена в конце. Замена строки в этом формате обычно выглядит как пара «минус старая, плюс новая».

Контекста в формате -u по умолчанию показывается по три строки до и после изменения, а число меняется ключом -U (например, -U 1); сверьтесь со справкой своей версии. Для просмотра объёмных результатов пропустите вывод через less. В новых версиях GNU diff есть ключ --color для подсветки, но он поддерживается не везде, поэтому проверяйте diff --help в своей системе.

🛡️ Остались проблемы с соединением?
Можно пользоваться постоянно: российские приложения работают, включать и выключать ничего не нужно. Без карты и регистрации, настройка за пару минут.
Попробовать бесплатно

Ключи, которые нужны чаще всего

Базовый вызов хорошо дополняют несколько ключей. Все они перечислены в справке diff и работают в GNU-версии на Linux и в версии для macOS, но проверка своей системы не помешает.

КлючЧто делает
-uунифицированный формат со знаками + и -
-qне показывает разницу, только сообщает, отличаются ли файлы
-rрекурсивно сравнивает каталоги
-iигнорирует различия в регистре букв
-wигнорирует пробелы и табуляции
-x шаблонисключает файлы по шаблону при сравнении каталогов

Ключ -w выручает, когда файл прогнали через редактор, поменявший отступы: без него diff покажет изменённой каждую строку. Ключ -i подходит для сравнения текстов, где регистр не важен.

Для двоичных файлов построчное сравнение бессмысленно. diff в таком случае сообщает только, что файлы различаются. Если нужно узнать, совпадают ли они байт в байт, используют команду cmp или сравнивают контрольные суммы, как показано в статье про md5sum и shasum.

Сравнение двух папок

Чтобы сравнить каталоги, добавьте -r. Команда diff -rq dir1 dir2 даёт короткий отчёт: в нём перечислены файлы, которые различаются, а также файлы, имеющиеся только в одном из каталогов, в формате «Only in имя каталога: имя файла». Такой обзор помогает быстро оценить масштаб расхождений перед сверкой деталей.

Если опустить -q и добавить -u, вы получите различия по каждому файлу. Для больших деревьев вывод получается длинным, поэтому сохраняйте его в файл через перенаправление или используйте tee, а затем просматривайте постепенно.

Полезный сценарий: вы сделали копию папки и хотите проверить, идентична ли она оригиналу. Запустите diff -rq оригинал копия. Пустой вывод и код возврата 0 означают, что набор имён и содержимое файлов совпадают, а код 1 говорит о различиях. Для сравнения прав, владельцев и времён diff не подходит: он смотрит на содержимое и наличие имён. Для метаданных пригодится stat.

Для плановой синхронизации деревьев удобнее rsync с пробным запуском: он сразу показывает, что передать, а не просто констатирует различие, и об этом есть отдельные материалы.

Сравнение вывода двух команд без временных файлов

Иногда нужно сравнить не файлы, а результаты команд: список пакетов до и после обновления, содержимое каталога на двух дисках, вывод ls в разные моменты. Создавать для этого временные файлы необязательно. В оболочках bash и zsh есть подстановка процесса, которая выглядит как <(команда) и подставляет вывод команды как файл. Пример: diff <(ls папка1) <(ls папка2) сравнит списки имён в двух папках.

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

Несколько практических замечаний:

  • у сравнения вывода двух команд тоже есть код возврата, поэтому его можно использовать в проверках;
  • сортировка перед сравнением убирает различия в порядке строк: diff <(sort a.txt) <(sort b.txt);
  • если сравниваются списки по тексту, различия в окончаниях строк (Windows и Unix) иногда делают все строки «разными»: в таком случае проверьте формат файлов командой file или поищите в справке ключ для игнорирования (в GNU diff это --strip-trailing-cr, в других версиях его может не быть).

Изменения, найденные diff, не применяются сами. Для их автоматического наложения существует отдельная команда patch, но это уже тема, выходящая за рамки статьи.

🛡️ Остались проблемы с соединением?
Можно пользоваться постоянно: российские приложения работают, включать и выключать ничего не нужно. Без карты и регистрации, настройка за пару минут.
Попробовать бесплатно
diffсравнениеlinuxmacosфайлы

Часто задаваемые вопросы

Читайте также