Команда diff: сравнение файлов, формат патча diff -u и опции

Тестовая средаСемейство RHELAlmaLinux 9.8Учётная запись root

Команда diff — это команда Linux, которая построчно сравнивает два файла и выводит только различающиеся строки. При сравнении через diff старого и нового файлов, имитирующих конфигурацию веб-сервера, три изменённых места были показаны тремя строками 2,3c2,3, 5d4 и 6a6, а в файле патча, сохранённом с опцией -u, те же изменения были оформлены знаками минус и плюс.

Имена и содержимое файлов в выводе ниже и рабочая папка /root/work приведены для примера. Все сравниваемые файлы — небольшие файлы, созданные для проверки.

1️⃣ Базовое использование команды diff и чтение вывода

Базовая форма команды — по порядку diff, опции, первый файл и второй файл. Команда выводит с номерами строк, какие строки нужно изменить, удалить или добавить, чтобы первый файл стал таким же, как второй.

Два файла, использованные для сравнения, — это файлы из шести строк, имитирующие конфигурацию веб-сервера.

cd /root/work
cat config-old.conf
# app config
listen 80
server_name example.com
root /var/www/html
gzip off
log_level warn
cat 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.conf
2,3c2,3
< listen 80
< server_name example.com
---
> listen 443
> server_name example.com www.example.com
5d4
< gzip off
6a6
> cache on
echo $?
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.conf
echo $?
0

Если указать несуществующий файл, появляется сообщение об ошибке, а код завершения равен 2.

diff config-old.conf nosuch.conf
diff: nosuch.conf: No such file or directory
echo $?
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.patch
echo $?
1
cat /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.txt
Listen 80
ServerName example.com
DocumentRoot /var/www/html
cat case-b.txt
listen 80
ServerName  example.com

DocumentRoot /var/www/html
diff case-a.txt case-b.txt
1,2c1,3
< Listen 80
< ServerName example.com
---
> listen 80
> ServerName  example.com
>

При сравнении без опций строки 1–2, одинаковые по смыслу, тоже показаны как изменённые. Если игнорировать регистр через -i, строка Listen исчезает и остаётся только строка 2 первого файла.

diff -i case-a.txt case-b.txt
2c2,3
< ServerName example.com
---
> ServerName  example.com
>

С добавлением -w игнорируются все пробелы внутри строки, поэтому строка ServerName тоже становится одинаковой и остаётся только одна пустая строка, добавленная в строке 3. С опцией -b, которая игнорирует только количество пробелов, вместо -w результат для этих файлов был тем же.

diff -i -w case-a.txt case-b.txt
2a3
>

Если добавить ещё и -B, различия в пустых строках тоже игнорируются, поэтому команда завершилась без вывода с кодом 0.

diff -i -w -B case-a.txt case-b.txt
echo $?
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.conf
listen 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.conf
Files config-old.conf and config-new.conf differ
diff -s config-old.conf config-copy.conf
Files 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 и сравнить снова, появится изменённый результат.

Симулятор команды diffdiff · Учётная запись root
[root@server work]#
Клавишами ↑↓ можно вызвать ранее введённые команды.

4️⃣ Сравнение папок через diff -r

Чтобы сравнить сразу несколько файлов, например до и после развёртывания файлов сайта, вместо файлов укажите имена папок. В папках-примерах site-v1 и site-v2 есть index.html и папка css, а about.html и contact.html есть только с одной стороны.

diff site-v1 site-v2
Only 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-v2
Only 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-v2
Only 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 & рекомендуемые материалы

cmp сравнивает два файла побайтно и выводит только первую позицию, где они различаются. Сравнение через cmp двух файлов конфигурации из статьи дало одну строку [config-old.conf config-new.conf differ: char 21, line 2]. Команду используют, чтобы проверить, одинаковы ли сжатые файлы или изображения, для которых построчное сравнение не имеет смысла.

Передайте команде patch по порядку исходный файл и файл патча ([patch config-old.conf config.patch]). patch изменяет исходный файл на месте, поэтому запишите результат в другой файл через -o или сначала примените патч к копии.

Опция --color[=WHEN] добавляет цвет, а на месте WHEN указывается never, always или auto. --color без значения равнозначна auto и добавляет цвет только при выводе в терминал, поэтому, чтобы сохранить цвет и при передаче вывода другой команде, например less, используйте --color=always.

🪐ИсточникиОфициальные источники 3

ℹ️ О партнёрских ссылках
Материалы этого сайта содержат партнёрские ссылки. Если посетитель покупает товар или услугу по такой ссылке, сайт получает комиссию от продавца. При этом сумма, которую платит покупатель (при акционных скидках сумма снижается ↓), не увеличивается. Указанные цены, скидки и наличие актуальны на момент написания и могут отличаться, поэтому перед покупкой уточняйте их у продавца. Товары выбираются и оцениваются по нашим собственным критериям, а комиссия не влияет ни на порядок, ни на содержание обзоров.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Докажите, что вы человек: 7   +   2   =