Полное руководство по опциям команды diff
Введение
В первой части серии руководств по команде diff были разъяснены базовые принципы работы инструмента и как интерпретировать его вывод. Хотя у команды есть небольшая кривая обучения, её стоит освоить, если ваша работа связана с файловыми операциями на Linux-серверах без графического интерфейса.
В этой части, предполагая, что вы знакомы с базовым использованием diff, мы подробно разберём ключевые опции утилиты на понятных примерах.
Важно: все примеры в этой статье проверялись на Ubuntu 14.04 с Bash 4.3.11(1) и diff 3.3.
Основные опции команды diff
Ниже — набор часто используемых опций. Каждый пункт содержит пример вывода и краткое пояснение.
1. Сообщать, когда файлы идентичны
По умолчанию diff не выводит ничего, если файлы одинаковы:
$ diff file1 file2
$Опция -s заставляет diff сообщать об идентичности файлов:
$ diff -s file1 file2
Files file1 and file2 are identical2. Контекстный и unified форматы
diff может выводить различия в формате “контекст” (context) и “unified”. Контекст активируется ключом -c, unified — -u.
Пример контекстного вывода:
$ diff -c file1 file2
* file1 2016-12-29 09:36:47.175597647 +0530
--- file2 2016-12-29 09:19:55.799558326 +0530
***********
* 1,3 **
Hi
! Helllo
Bye
--- 1,3 ----
Hi
! Hello
ByeВ контекстном формате строки с отличиями помечаются знаком восклицания (!).
Пример unified-вывода:
$ diff -u file1 file2
--- file1 2016-12-29 09:36:47.175597647 +0530
+++ file2 2016-12-29 09:19:55.799558326 +0530
@@ -1,3 +1,3 @@
Hi
-Helllo
+Hello
ByeВ unified-формате строки с “+” — добавленные, со “-“ — удалённые относительно первого файла.
3. Вывести скрипт для редактора ed
diff может сгенерировать команды для редактора ed, чтобы превратить исходный файл в новый. Допустим, у нас такая разница:
$ diff file1 file2
2c2
< Helllo
---
> HelloЧтобы получить ed-скрипт, используйте -e и перенаправьте вывод в файл:
diff -e file1 file2 > outСодержимое out:
2c
Hello
.Добавьте команду записи w в конец out
2c Hello .w
И выполните:
ed - file1 < outПосле этого file1 станет идентичен file2.
Примечание: ed-скрипты полезны в ограниченных средах или при автоматизированных правках на хостах без современных редакторов.
4. Вывести результат в две колонки
Опция -y выводит сравнение столбцами — удобно для быстрого визуального сопоставления:
$ diff -y file1 file2
Hi Hi
Helllo | Hello
Bye ByeСимвол ‘|’ указывает строки, отличающиеся между файлами.
5. Скрыть одинаковые строки
При выводе в две колонки опция –suppress-common-lines убирает общие строки, оставляя только отличия:
himanshu@himanshu-desktop:~$ diff -y --suppress-common-lines file1 file2
Helllo | Hello6. Показать, в какой C-функции находится изменение
Опция -p показывает имя C-функции, в которой находится изменение — полезно для сравнений исходников C/C++.
file1.c:
#include
void compare(float x, float y)
{
if(x == y) // incorrect way
{
printf("\n EQUAL \n");
}
}
int main(void)
{
compare(1.234, 1.56789);
return 0;
} file2.c:
#include
void compare(float x, float y)
{
if(x == y)
{
printf("\n EQUAL \n");
}
}
int main(void)
{
compare(1.234, 1.56789);
return 0;
} Обычный вывод:
$ diff file1.c file2.c
5c5
< if(x == y) // incorrect way
---
> if(x == y)А с -p:
$ diff -p file1.c file2.c* file1.c 2016-12-29 11:45:36.587010816 +0530 --- file2.c 2016-12-29 11:46:39.823013274 +0530 ************* * 2,8 ** void compare(float x, float y) { ! if(x == y) // incorrect way { printf("\n EQUAL \n"); } --- 2,8 ---- void compare(float x, float y) { ! if(x == y) { printf("\n EQUAL \n"); }
Опция -p даёт контекст имени функции рядом с изменениями.
7. Рекурсивное сравнение поддиректорий
По умолчанию diff сравнивает только файлы верхнего уровня. Ключ -r включает рекурсию и позволяет сравнить содержимое поддиректорий:
$ diff diff-files/ second-diff-files/
diff diff-files/file1 second-diff-files/file1
1c1
< Hi
---
> i
diff diff-files/file2 second-diff-files/file2
2c2
< Hello
---
> elloС -r будут включены и вложенные каталоги:
$ diff -r diff-files/ second-diff-files/ diff -r diff-files/file1 second-diff-files/file1 1c1 < Hi --- > i diff -r diff-files/file2 second-diff-files/file2 2c2 < Hello --- > ellodiff -r diff-files/more-diff-files/file1 second-diff-files/more-diff-files/file1 1c1 < Hi --- > i diff -r diff-files/more-diff-files/file2 second-diff-files/more-diff-files/file2** 2c2 < Hello --- > ello
8. Считать отсутствующие файлы пустыми
По умолчанию diff выдаёт ошибку, если один из файлов отсутствует:
$ diff file1 file3
diff: file3: No such file or directoryОпция -N заставляет трактовать отсутствующий файл как пустой и продолжать сравнение:
$ diff -N file1 file3
1,5d0
< Hi
<
< Helllo
<
< ByeЭто удобно в скриптах, где отсутствие файла не должно прерывать поток обработки.
Полезные сочетания и примеры применения
- Быстро узнать, отличаются ли файлы (короткий отчёт):
diff -q file1 file2- Получить патч в формате unified для передачи или применения через patch:
diff -u oldfile newfile > change.patch
patch -p0 < change.patch- Рекурсивно сравнить каталоги и игнорировать отсутствующие файлы:
diff -ruN dir_old/ dir_new/- Цветной вывод (через обёртку colordiff):
colordiff -u a bКогда diff показывает неверные или неполные результаты
Important: diff сравнивает содержимое файлов построчно. Вот случаи, когда результаты могут быть неудобными или вводить в заблуждение:
- Файлы имеют разные кодировки (например, UTF-8 vs ISO-8859-1) — визуально похожие символы будут отличаться на байтовом уровне.
- Разные окончания строк (CRLF vs LF) — приведут к лишним изменениям; используйте dos2unix/unix2dos или игнорируйте различия через prdiff/awk.
- Большие бинарные файлы — diff предназначён для текстовых файлов; для бинарных сравнение даёт мало смысла (используйте cmp или хеши: sha256sum).
- Изменения в порядке строк (перестановки) считаются большим изменением — diff не распознаёт семантическую эквивалентность.
В подобных ситуациях рассмотрите альтернативы (ниже) или подготовьте предобработку файлов (нормализация окончаний строк, сортировка, фильтрация ненужных полей).
Альтернативы и дополнения
- git diff — удобен для репозиториев, показывает изменения в контексте коммитов и умеет работать с индексом.
- cmp — побайтовое сравнение, возвращает первое различие; полезно для бинарных файлов.
- rsync –dry-run — для сравнения содержимого директорий и подготовки синхронизации.
- meld, kdiff3 — графические визуализаторы различий.
- colordiff — цветной обёрток вокруг diff для удобства чтения в терминале.
Выбор инструмента зависит от цели: патч для передачи, быстрая проверка совпадения, визуальная ревизия или синхронизация.
Скриншот методики использования (мини-методология)
- Нормализуйте входные файлы: кодировка UTF-8, одинаковые окончания строк.
- Используйте опции, подходящие по цели: -u для патчей, -y для визуальной проверки, -r для директорий.
- Для автоматизации — комбинируйте -q/-s и проверяйте код возврата (0/1/2). 0 — идентично, 1 — различия, 2 — ошибка.
- При необходимости генерируйте патчи: diff -u > patch и применяйте patch -p.
Чеклисты по ролям
Разработчик:
- Проверить кодировку и окончания строк.
- Создать unified-патч: diff -u.
- Протестировать применение патча на копии.
Системный администратор:
- Сравнить конфиги в каталоге: diff -ruN /etc/save/ /etc/current/.
- Игнорировать временные файлы через –exclude (в оболочке или rsync).
Код-ревьюер:
- Использовать -u для читаемого патча.
- При большом патче разбивать изменения по логическим блокам.
Тестировщик:
- Проверить, что функциональные изменения в коде отражены в тестах.
- Использовать diff для проверки вывода логов между версиями.
Шпаргалка по опциям
- -s — сообщить, если файлы идентичны
- -c — контекстный формат
- -u — unified формат (патчи)
- -e — вывести ed-скрипт
- -y — две колонки
- –suppress-common-lines — скрыть одинаковые строки в -y
- -p — показать C-функции
- -r — рекурсивно
- -N — считать отсутствующие файлы пустыми
- -q — короткий режим: только факт отличия
Примеры:
diff -ruN /backup/etc/ /etc/ > etc-changes.patch
colordiff -u a.py b.py | less -R
diff -y --suppress-common-lines old.txt new.txtФакты и коды возврата
- Возврат 0 — файлы идентичны.
- Возврат 1 — файлы различаются.
- Возврат 2 — произошла ошибка (например, файл не найден и не использовалась -N).
Применение патчей и совместимость
- Формат unified (-u) совместим с утилитой patch и системами контроля версий.
- Для переноса изменений между машинами используйте: diff -u old new > change.patch и затем patch -p0 < change.patch.
Совместимость: diff является стандартной утилитой GNU; поведение опций может незначительно отличаться в других реализациях (например, BSD diff). При переносе скриптов учитывайте среду исполнения.
Критерии приёмки
- Для автоматической проверки: diff -q ожидаемый фактический; выход 0 — тест пройден.
- Для ревью патча: unified-патч должен применяться без конфликта командой patch.
- Для синхронизации конфигураций: после применения патча содержимое должно совпадать и служба успешно перезапуститься.
Заключение
Если вы внимательно пройдёте обе части руководства и попрактикуетесь на разных сценариях, вы получите уверенное владение diff. Мы рассмотрели ключевые опции, полезные сочетания и типичные случаи, когда diff не подходит и требуется предобработка данных или другие инструменты.
Notes: man diff остаётся главным источником по неописанным здесь деталям: используйте man diff или info diff для полного справочника.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента