Polecenie diff: porównywanie plików, format łatki diff -u i opcje

Środowisko testoweRodzina RHELAlmaLinux 9.8konto root
Polecenia do przeglądania · edycji tekstudiffLokalizacja/usr/bin/diff

Polecenie diff to polecenie Linuksa, które porównuje dwa pliki wiersz po wierszu i wypisuje tylko wiersze różniące się. Porównanie przez diff starego i nowego pliku, które naśladują konfigurację serwera WWW, pokazało trzy zmienione miejsca w trzech wierszach 2,3c2,3, 5d4 i 6a6, a w pliku łatki zapisanym z opcją -u te same zmiany były uporządkowane znakami minus i plus.

Nazwy i zawartość plików w poniższych wynikach oraz folder roboczy /root/work to wartości przykładowe. Wszystkie porównywane pliki to małe pliki utworzone do testów.

1️⃣ Podstawowe użycie polecenia diff i czytanie wyniku

Podstawowa postać polecenia to kolejno diff, opcje, pierwszy plik i drugi plik. Polecenie wypisuje z numerami wierszy, które wiersze trzeba zmienić, usunąć lub dodać, żeby pierwszy plik stał się taki sam jak drugi.

Dwa pliki użyte do porównania to sześciowierszowe pliki naśladujące konfigurację serwera WWW.

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

Oba pliki porównano bez opcji.

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

W wyniku na przemian pojawiają się wiersze pozycji i wiersze treści. Środkowa litera wiersza pozycji to c dla zmiany, d dla usunięcia i a dla dodania; na lewo od litery stoją numery wierszy pierwszego pliku, na prawo drugiego. Gdy są różnice, kod wyjścia wynosi 1.

WynikZnaczenie
2,3c2,3Zmienia wiersze 2–3 pierwszego pliku na wiersze 2–3 drugiego pliku (change)
5d4Usuwa wiersz 5 pierwszego pliku (delete). Po usunięciu zgadza się z miejscem za wierszem 4 drugiego pliku
6a6Dodaje wiersz 6 drugiego pliku za wierszem 6 pierwszego pliku (add)
< wierszWiersz z pierwszego pliku
> wierszWiersz z drugiego pliku
---Granica między stroną pierwszego pliku a stroną drugiego pliku w zmienianych wierszach (c)

Przy porównaniu plików o tej samej zawartości nic nie jest wypisywane, a polecenie kończy się kodem wyjścia 0.

diff config-old.conf config-copy.conf
echo $?
0

Po podaniu pliku, który nie istnieje, pojawia się komunikat o błędzie, a kod wyjścia wynosi 2.

diff config-old.conf nosuch.conf
diff: nosuch.conf: No such file or directory
echo $?
2

W skrypcie te trzy wartości pozwalają odróżnić: takie same, różne i błąd.

2️⃣ Format ujednolicony diff -u i plik łatki

Domyślny wynik zawiera tylko zmienione wiersze, więc w pliku konfiguracyjnym liczącym setki wierszy trudno znaleźć, przy którym ustawieniu się znajdują. Po dodaniu -u wynik ma format ujednolicony (unified), który łączy zmienione wiersze z maksymalnie trzema wierszami przed nimi i po nich.

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

Dwa wiersze nagłówka (---, +++) zawierają nazwy i czas modyfikacji obu plików, a wiersz @@ -1,6 +1,6 @@ oznacza blok (hunk), który łączy 6 wierszy od wiersza 1 pierwszego pliku z 6 wierszami od wiersza 1 drugiego pliku. W wierszach poniżej początkowy - oznacza wiersz usunięty z pierwszego pliku, + wiersz dodany do drugiego pliku, a spacja wiersz identyczny w obu plikach.

-c to format kontekstowy (context). Blok pierwszego pliku i blok drugiego pliku są wypisywane osobno, z wykrzyknikiem przed zmienionymi wierszami, minusem przy usuniętych i plusem przy dodanych.

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

Przy tych samych zmianach wynik -c był dłuższy niż -u, bo niezmienione wiersze pojawiają się po razie w każdym z dwóch bloków.

Zapisanie wyniku -u do pliku daje od razu plik łatki. Także po skierowaniu wyniku do pliku kod wyjścia diff nadal wynosi 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

Zawartość zapisanego pliku jest taka sama jak wynik -u wypisany na ekranie. Po przekazaniu tego pliku poleceniu patch pierwszy plik można doprowadzić do tej samej zawartości co drugi.

3️⃣ Opcje diff oraz ignorowanie spacji i wielkości liter

Przy ręcznym przepisywaniu ustawień powstają wiersze o tej samej treści, różniące się tylko wielkością liter lub spacjami. W drugiej parze plików przykładowych wielkie L w pierwszym wierszu zmieniono na małe, jedną spację w drugim wierszu na dwie i dodano jeden pusty wiersz.

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
>

Przy porównaniu bez opcji wiersze 1–2, które znaczą to samo, też pojawiają się jako zmienione. Po zignorowaniu wielkości liter przez -i wiersz Listen znika i zostaje tylko wiersz 2 pierwszego pliku.

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

Po dodaniu -w ignorowane są wszystkie spacje w wierszu, więc wiersz ServerName też staje się taki sam i zostaje tylko jeden pusty wiersz dodany w wierszu 3. Po wstawieniu zamiast -w opcji -b, która ignoruje tylko liczbę spacji, wynik dla tych plików był taki sam.

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

Po dodaniu jeszcze -B ignorowane są także różnice w pustych wierszach, więc polecenie zakończyło się bez wyniku, z kodem wyjścia 0.

diff -i -w -B case-a.txt case-b.txt
echo $?
0

Do oglądania dwóch plików obok siebie, po lewej i po prawej, służy -y. Domyślna szerokość to 130 kolumn, dlatego zmniejszono ją przez -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

Pionowa kreska (|) pośrodku oznacza zmieniony wiersz, < wiersz obecny tylko w pierwszym pliku, a > wiersz obecny tylko w drugim pliku. Po zwężeniu długie wiersze są obcinane. Wiersz server_name pojawił się po prawej tylko do www.ex.

Po dodaniu --suppress-common-lines takie same wiersze są pomijane i zostają tylko różne.

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

Do sprawdzenia tylko tego, czy pliki są takie same, czy różne, a nie treści różnic, służy -q. Gdy pliki są takie same, -q nic nie wypisuje, więc do uzyskania wiersza z informacją, że są identyczne, służy -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

Opcje zebrano w dwóch kartach poniżej.

OpcjaKopiujOpis
-u, --unifiedWypisuje w formacie ujednoliconym, który łączy zmienione wiersze z maksymalnie trzema wierszami przed nimi i po nich
-c, --contextFormat kontekstowy, który wypisuje osobno blok pierwszego pliku i blok drugiego pliku
-i, --ignore-caseIgnoruje różnice w wielkości liter
-w, --ignore-all-spaceIgnoruje wszystkie spacje w wierszu
-b, --ignore-space-changeIgnoruje tylko różnice w liczbie spacji
-B, --ignore-blank-linesIgnoruje różnice w pustych wierszach
-y, --side-by-sideWypisuje dwa pliki obok siebie, po lewej i po prawej
-W, --widthNUMUstawia szerokość wyniku obok siebie. Wartość domyślna to 130 kolumn
--suppress-common-linesW wyniku obok siebie pomija takie same wiersze i wypisuje tylko różne
-q, --briefWypisuje tylko, czy pliki są takie same, czy różne. Gdy są takie same, nic nie wypisuje
-s, --report-identical-filesGdy dwa pliki są takie same, wypisuje wiersz z informacją, że są identyczne
-r, --recursivePorównuje także pliki w podfolderach
OpcjaKopiujOpis
-U, --unifiedNUMUstawia liczbę wierszy przed i po wypisywanych razem w formacie ujednoliconym. Wartość domyślna to 3
-N, --new-fileTraktuje plik, którego brakuje po jednej stronie, jak pusty plik
-x, --excludePATWyklucza z porównania pliki o nazwach pasujących do wzorca
-I, --ignore-matching-linesREIgnoruje różnicę, jeśli wszystkie zmienione wiersze pasują do wyrażenia regularnego
-Z, --ignore-trailing-spaceIgnoruje spacje na końcu wiersza
-E, --ignore-tab-expansionIgnoruje różnice powstałe przez zamianę tabulatorów na spacje
-a, --textTraktuje wszystkie pliki jak tekst
--strip-trailing-crUsuwa znak powrotu karetki z końca wiersza przed porównaniem
--colorWHENKoloruje wynik. WHEN to never, always lub auto
-v, --versionWypisuje informacje o wersji

🔲 Symulator polecenia diff

W symulatorze poniżej można samodzielnie wpisać diff z plikami przykładowymi z artykułu. Można zapisać plik łatki przez -u albo porównać przez -i -w -B i -rq, a po dodaniu wiersza do config-new.conf i ponownym porównaniu pojawia się zmieniony wynik.

Symulator polecenia diffdiff · konto root
[root@server work]#
Klawiszami ↑↓ przywołasz wcześniej wpisane polecenia.

4️⃣ Porównywanie folderów przez diff -r

Przy porównywaniu wielu plików naraz, na przykład przed wdrożeniem plików witryny i po nim, zamiast plików podaje się nazwy folderów. Przykładowe foldery site-v1 i site-v2 zawierają oba index.html i folder css, a about.html i contact.html są tylko po jednej stronie.

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>

Przy porównaniu folderów bez opcji pliki obecne tylko po jednej stronie pojawiają się jako wiersze [Only in], a podfoldery tylko jako wiersze [Common subdirectories]; pliki w podfolderach nie są porównywane. Dla index.html, który jest pod tą samą nazwą w obu folderach, różnice są wypisywane pod wierszem [diff site-v1/index.html site-v2/index.html]. Po dodaniu -r wypisywana jest też zmieniona wartość koloru w style.css w folderze 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>

W folderze z wieloma plikami najpierw sprawdza się przez -rq listę zmienionych plików, a potem ponownie porównuje przez diff tylko potrzebne pliki.

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 & polecane treści

cmp porównuje dwa pliki bajt po bajcie i wypisuje tylko pierwsze miejsce, w którym się różnią. Porównanie przez cmp dwóch plików konfiguracyjnych z artykułu dało jeden wiersz [config-old.conf config-new.conf differ: char 21, line 2]. Służy do sprawdzania, czy takie same są pliki skompresowane lub obrazy, dla których porównywanie wiersz po wierszu nie ma sensu.

Poleceniu patch przekazuje się kolejno plik oryginalny i plik łatki ([patch config-old.conf config.patch]). patch zmienia plik oryginalny w miejscu, dlatego wynik zapisuje się przez -o do innego pliku albo najpierw stosuje łatkę na kopii.

Opcja --color[=WHEN] dodaje kolor, a w miejscu WHEN wpisuje się never, always lub auto. --color bez wartości działa jak auto i dodaje kolor tylko przy wypisywaniu na terminal, więc żeby zachować kolor także przy przekazywaniu wyniku do innego polecenia, takiego jak less, używa się --color=always.

ℹ️ Informacja o linkach partnerskich
Treści tej witryny zawierają linki partnerskie. Jeśli odwiedzający kupi produkt lub usługę przez taki link, witryna otrzymuje od sprzedawcy prowizję. Kwota płacona przy tym przez kupującego (podczas promocji spada↓) nie wzrasta. Podane ceny, rabaty i dostępność odnoszą się do chwili pisania i mogą różnić się od stanu faktycznego, dlatego przed zakupem sprawdź je u sprzedawcy. Produkty wybieramy i oceniamy według własnych kryteriów, a prowizja nie wpływa ani na kolejność prezentacji, ani na treść ocen.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *

Prove your humanity: 4   +   8   =