Команда diff: сравнение файлов, формат патча diff -u и опции
Команда diff — это команда Linux, которая построчно сравнивает два файла и выводит только различающиеся строки. При сравнении через diff старого и нового файлов, имитирующих конфигурацию веб-сервера, три изменённых места были показаны тремя строками 2,3c2,3, 5d4 и 6a6, а в файле патча, сохранённом с опцией -u, те же изменения были оформлены знаками минус и плюс.
Имена и содержимое файлов в выводе ниже и рабочая папка /root/work приведены для примера. Все сравниваемые файлы — небольшие файлы, созданные для проверки.
1️⃣ Базовое использование команды diff и чтение вывода
Базовая форма команды — по порядку diff, опции, первый файл и второй файл. Команда выводит с номерами строк, какие строки нужно изменить, удалить или добавить, чтобы первый файл стал таким же, как второй.
Два файла, использованные для сравнения, — это файлы из шести строк, имитирующие конфигурацию веб-сервера.
cd /root/workcat config-old.conf# app config
listen 80
server_name example.com
root /var/www/html
gzip off
log_level warncat config-new.conf# app config
listen 443
server_name example.com www.example.com
root /var/www/html
log_level warn
cache onДва файла сравнили без опций.
diff config-old.conf config-new.conf2,3c2,3
< listen 80
< server_name example.com
---
> listen 443
> server_name example.com www.example.com
5d4
< gzip off
6a6
> cache onecho $?1В выводе чередуются строки позиции и строки содержимого. Буква в середине строки позиции означает: c — изменение, d — удаление, a — добавление; слева от буквы стоят номера строк первого файла, справа — второго. Если есть различия, код завершения равен 1.
| Вывод | Назначение |
|---|---|
| 2,3c2,3 | Заменяет строки 2–3 первого файла строками 2–3 второго файла (change) |
| 5d4 | Удаляет строку 5 первого файла (delete). После удаления место совпадает с позицией после строки 4 второго файла |
| 6a6 | Добавляет строку 6 второго файла после строки 6 первого файла (add) |
| < строка | Строка из первого файла |
| > строка | Строка из второго файла |
| --- | Граница между стороной первого файла и стороной второго файла в изменяемых строках (c) |
При сравнении файлов с одинаковым содержимым ничего не выводится, и команда завершается с кодом 0.
diff config-old.conf config-copy.confecho $?0Если указать несуществующий файл, появляется сообщение об ошибке, а код завершения равен 2.
diff config-old.conf nosuch.confdiff: nosuch.conf: No such file or directoryecho $?2В скрипте по этим трём значениям различают: одинаковы, различаются и ошибка.
2️⃣ Унифицированный формат diff -u и файл патча
В обычном выводе есть только изменённые строки, поэтому в файле конфигурации из сотен строк трудно понять, рядом с какой настройкой они находятся. С опцией -u вывод идёт в унифицированном формате (unified), который захватывает до трёх строк до и после изменённых строк.
diff -u config-old.conf config-new.conf--- config-old.conf 2026-10-29 02:24:50.840228932 +0000
+++ config-new.conf 2026-10-29 02:24:50.840228932 +0000
@@ -1,6 +1,6 @@
# app config
-listen 80
-server_name example.com
+listen 443
+server_name example.com www.example.com
root /var/www/html
-gzip off
log_level warn
+cache onДве строки заголовка (---, +++) содержат имена и время изменения двух файлов, а строка @@ -1,6 +1,6 @@ обозначает блок (hunk), объединяющий 6 строк начиная со строки 1 первого файла и 6 строк начиная со строки 1 второго файла. В строках ниже начальный - означает строку, удалённую из первого файла, + — строку, добавленную во второй файл, а пробел — строку, одинаковую в обоих файлах.
-c — это контекстный формат (context). Блок первого файла и блок второго файла выводятся отдельно: перед изменёнными строками стоит восклицательный знак, у удалённых — минус, у добавленных — плюс.
diff -c config-old.conf config-new.conf*** config-old.conf Thu Oct 29 02:24:50 2026
--- config-new.conf Thu Oct 29 02:24:50 2026
***************
*** 1,6 ****
# app config
! listen 80
! server_name example.com
root /var/www/html
- gzip off
log_level warn
--- 1,6 ----
# app config
! listen 443
! server_name example.com www.example.com
root /var/www/html
log_level warn
+ cache onПри тех же изменениях вывод -c получился длиннее, чем -u, потому что неизменённые строки встречаются по одному разу в каждом из двух блоков.
Если сохранить вывод -u в файл, этот файл и будет файлом патча. Даже при перенаправлении вывода в файл код завершения diff остаётся равным 1.
diff -u config-old.conf config-new.conf > /root/work/config.patchecho $?1cat /root/work/config.patch--- config-old.conf 2026-10-29 02:24:50.840228932 +0000
+++ config-new.conf 2026-10-29 02:24:50.840228932 +0000
@@ -1,6 +1,6 @@
# app config
-listen 80
-server_name example.com
+listen 443
+server_name example.com www.example.com
root /var/www/html
-gzip off
log_level warn
+cache onСодержимое сохранённого файла совпадает с результатом -u, выведенным на экран. Если передать этот файл команде patch, первый файл можно привести к тому же содержимому, что и второй.
3️⃣ Опции diff и игнорирование пробелов и регистра
При переносе настроек вручную появляются строки с одинаковым содержимым, которые отличаются только регистром или пробелами. Во второй паре файлов-примеров заглавная L в первой строке заменена строчной, один пробел во второй строке — двумя, и добавлена одна пустая строка.
cat case-a.txtListen 80
ServerName example.com
DocumentRoot /var/www/htmlcat case-b.txtlisten 80
ServerName example.com
DocumentRoot /var/www/htmldiff case-a.txt case-b.txt1,2c1,3
< Listen 80
< ServerName example.com
---
> listen 80
> ServerName example.com
>При сравнении без опций строки 1–2, одинаковые по смыслу, тоже показаны как изменённые. Если игнорировать регистр через -i, строка Listen исчезает и остаётся только строка 2 первого файла.
diff -i case-a.txt case-b.txt2c2,3
< ServerName example.com
---
> ServerName example.com
>С добавлением -w игнорируются все пробелы внутри строки, поэтому строка ServerName тоже становится одинаковой и остаётся только одна пустая строка, добавленная в строке 3. С опцией -b, которая игнорирует только количество пробелов, вместо -w результат для этих файлов был тем же.
diff -i -w case-a.txt case-b.txt2a3
>Если добавить ещё и -B, различия в пустых строках тоже игнорируются, поэтому команда завершилась без вывода с кодом 0.
diff -i -w -B case-a.txt case-b.txtecho $?0Чтобы увидеть два файла рядом, слева и справа, используйте -y. Ширина по умолчанию — 130 столбцов, поэтому её уменьшили через -W 70.
diff -y -W 70 config-old.conf config-new.conf# app config # app config
listen 80 | listen 443
server_name example.com | server_name example.com www.ex
root /var/www/html root /var/www/html
gzip off <
log_level warn log_level warn
> cache onВертикальная черта (|) посередине означает изменённую строку, < — строку только в первом файле, > — строку только во втором файле. При уменьшении ширины длинные строки обрезаются. Строка server_name справа была показана только до www.ex.
С добавлением --suppress-common-lines одинаковые строки убираются и остаются только различающиеся.
diff -y --suppress-common-lines -W 70 config-old.conf config-new.conflisten 80 | listen 443
server_name example.com | server_name example.com www.ex
gzip off <
> cache onЧтобы проверить только то, одинаковы файлы или различаются, а не содержание различий, используйте -q. Когда файлы одинаковы, -q ничего не выводит, поэтому для строки с сообщением, что они идентичны, используйте -s.
diff -q config-old.conf config-new.confFiles config-old.conf and config-new.conf differdiff -s config-old.conf config-copy.confFiles config-old.conf and config-copy.conf are identicalОпции собраны на двух вкладках ниже.
| Опция | Копировать | Описание |
|---|---|---|
| -u, --unified | Выводит в унифицированном формате, который захватывает до трёх строк до и после изменённых строк | |
| -c, --context | Контекстный формат, в котором блок первого файла и блок второго файла выводятся отдельно | |
| -i, --ignore-case | Игнорирует различия в регистре | |
| -w, --ignore-all-space | Игнорирует все пробелы внутри строки | |
| -b, --ignore-space-change | Игнорирует только различия в количестве пробелов | |
| -B, --ignore-blank-lines | Игнорирует различия в пустых строках | |
| -y, --side-by-side | Выводит два файла рядом, слева и справа | |
| -W, --widthNUM | Задаёт ширину вывода рядом. Значение по умолчанию — 130 столбцов | |
| --suppress-common-lines | При выводе рядом убирает одинаковые строки и выводит только различающиеся | |
| -q, --brief | Выводит только то, одинаковы файлы или различаются. Если одинаковы, ничего не выводит | |
| -s, --report-identical-files | Выводит строку с сообщением, что файлы идентичны, когда два файла одинаковы | |
| -r, --recursive | Сравнивает и файлы во вложенных папках |
| Опция | Копировать | Описание |
|---|---|---|
| -U, --unifiedNUM | Задаёт число строк до и после, выводимых вместе в унифицированном формате. Значение по умолчанию — 3 | |
| -N, --new-file | Считает файл, отсутствующий с одной стороны, пустым файлом | |
| -x, --excludePAT | Исключает из сравнения файлы, имена которых соответствуют шаблону | |
| -I, --ignore-matching-linesRE | Игнорирует различие, если все изменённые строки соответствуют регулярному выражению | |
| -Z, --ignore-trailing-space | Игнорирует пробелы в конце строки | |
| -E, --ignore-tab-expansion | Игнорирует различия, возникшие из-за замены табуляций пробелами | |
| -a, --text | Считает все файлы текстовыми | |
| --strip-trailing-cr | Убирает возврат каретки в конце строки перед сравнением | |
| --colorWHEN | Раскрашивает вывод. WHEN — never, always или auto | |
| -v, --version | Выводит сведения о версии |
🔲 Симулятор команды diff
В симуляторе ниже можно самостоятельно ввести diff с файлами-примерами из статьи. Можно сохранить файл патча через -u или сравнить через -i -w -B и -rq, а если добавить строку в config-new.conf и сравнить снова, появится изменённый результат.
4️⃣ Сравнение папок через diff -r
Чтобы сравнить сразу несколько файлов, например до и после развёртывания файлов сайта, вместо файлов укажите имена папок. В папках-примерах site-v1 и site-v2 есть index.html и папка css, а about.html и contact.html есть только с одной стороны.
diff site-v1 site-v2Only in site-v1: about.html
Only in site-v2: contact.html
Common subdirectories: site-v1/css and site-v2/css
diff site-v1/index.html site-v2/index.html
2,3c2,3
< <p>Version 1</p>
< <a href="about.html">About</a>
---
> <p>Version 2</p>
> <a href="contact.html">Contact</a>При сравнении папок без опций файлы, которые есть только с одной стороны, показаны строками [Only in], а вложенные папки — только строками [Common subdirectories]; файлы внутри вложенных папок не сравниваются. Для index.html, который есть под одним именем в обеих папках, различия выводятся под строкой [diff site-v1/index.html site-v2/index.html]. С опцией -r выводится и изменённое значение цвета в style.css в папке css.
diff -r site-v1 site-v2Only in site-v1: about.html
Only in site-v2: contact.html
diff -r site-v1/css/style.css site-v2/css/style.css
2c2
< h1 { color: #222; }
---
> h1 { color: #0a58ca; }
diff -r site-v1/index.html site-v2/index.html
2,3c2,3
< <p>Version 1</p>
< <a href="about.html">About</a>
---
> <p>Version 2</p>
> <a href="contact.html">Contact</a>В папке с большим числом файлов сначала проверьте через -rq список изменённых файлов, а затем снова сравните через diff только нужные файлы.
diff -rq site-v1 site-v2Only in site-v1: about.html
Only in site-v2: contact.html
Files site-v1/css/style.css and site-v2/css/style.css differ
Files site-v1/index.html and site-v2/index.html differ🔢 FAQ & рекомендуемые материалы
Linux · Текст
Команда grep в Linux
Как с помощью grep найти и вывести только строки с нужной подстрокой в текстовом файле, например в файле журнала.
Linux · Текст
Команда sort в Linux: сортировка файлов
Опции и примеры sort для сортировки содержимого файла по алфавиту, по возрастанию или по убыванию.
Linux · Текст
Команда uniq в Linux
Как с помощью uniq оставить только одну из повторяющихся строк и посчитать опцией -c, сколько раз она повторяется.
ℹ️ О партнёрских ссылках
Материалы этого сайта содержат партнёрские ссылки. Если посетитель покупает товар или услугу по такой ссылке, сайт получает комиссию от продавца. При этом сумма, которую платит покупатель (при акционных скидках сумма снижается ↓), не увеличивается. Указанные цены, скидки и наличие актуальны на момент написания и могут отличаться, поэтому перед покупкой уточняйте их у продавца. Товары выбираются и оцениваются по нашим собственным критериям, а комиссия не влияет ни на порядок, ни на содержание обзоров.