Archiwa i łaty


Archiwizujemy pliki (tar)

Zapewne pamiętamy z DOS-a polecenie BACKUP służące do tworzenia kopii zapasowych (archiwów). Do rozpakowania archiwów w DOS-ie używaliśmy RESTORE.

W Linuksie podobną funkcję spełnia tar (tape archiver). Za pomocą tar zarówno tworzymy pliki archiwów jak i je rozpakowujemy.

Elementarna znajomość tar jest niezbędna każdemu użytkownikowi Linuksa, gdyż archiwa .tar są jedną z podstawowych form rozpowszechniania aplikacji, tekstów źródłowych itp. Stosowany w Linuksie GNU tar ma szereg rozszerzeń w stosunku do standardowego, czyli spotykanego w innych systemach uniksowych. W szczególności dotyczy to możliwości dodatkowej kompresji i dekompresji pliku archiwum oraz tworzenia archiwów wielowarstwowych.

$ rm kat2/plik
[crash1@linux crash1]$ ls kat2
costutaj    costutaj2    naszplik    naszplik2
[crash1@linux crash1]$ tar -cf mojearch .
tar: mojearch is the archive; not dumped
[crash1@linux crash1]$ tar -tf mojearch .
./
.Xdefaults
.bash_logout
.bash_profile
.bashrc
.bash_history
.mc/
.mc/hotlist
.mc/ini
.mc/history
.cedit/
.cedit/syntax
kat2/
kat2/naszplik
kat2/naszplik2
kat2/costutaj
kat2/costutaj2
.bashrc_old
bin/
bin/zmk
[crash1@linux crash1]$ _
Utworzyliśmy (-c), a następnie wypisaliśmy zawartość (-t) archiwum (mojearch) dotyczącego bieżącego katalogu (.), czyli katalogu /home/crash1. Wykorzystaliśmy tu znak kropki (.) jako alias bieżącego katalogu. W obu przypadkach korzystamy z opcji -f wskazując, że tworzymy archiwum w postaci pliku dyskowego. Brak opcji -f powoduje, że tar będzie próbował tworzyć archiwum na domyślnym urządzeniu /dev/rmt0 (napędzie taśmowym), a jeśli go nie znajdzie to na standardowym wyjściu (ekranie).

Komunikat "mojearch is the archive; not dumped: otrzymamy po utworzeniu archiwum mówi nam właśnie o utworzeniu pliku mojearch, ale bez zrzucenia na taśmę.

Zauważmy, że tar domyślnie tworzy archiwum rekurencyjnie (z podkatalogami), umieszczając w nim wszystko co znajdzie we wskazanym katalogu (w tym plik i katalogi ukryte).

$ du mojearch
51  mojearch
[crash1@linux crash1]$ du
5         ./.mc
19        ./.cedit
6         ./.kat2
2         ./.bin
97        .
[crash1@linux crash1]$ du -b mojearch
51200  mojearch
[crash1@linux crash1]$ rm mojearch
[crash1@linux crash1]$ tar -cZf mojearch .
[crash1@linux crash1]$ du -b mojearch
13800  mojearch
[crash1@linux crash1]$ rm moje arch
[crash1@linux crash1]$ tar -czf mojearch
[crash1@linux crash1]$ du -b mojearch
7526  mojearch
[crash1@linux crash1]$ rm mojearch
[crash1@linux crash1]$ _
Poznaliśmy tu nowe polecenie du (disk usage). Pokazuje ono, ile kilobajtowych (1024-bajtowych) bloków dyskowych zajmuje wskazany plik (katalog). Podane bez argumentów wyprowadza listę wszystkich katalogów znajdujących się w bieżącym katalogu, wraz z podsumowaniem (w ostatnim wierszu listy). Chcąc uzyskać dokładniejszy rozmiar pliku musimy skorzystać z opcji -b - otrzymamy wtedy wynik w bajtach.

Normalnie tar tworzy nie skompresowane archiwum. W Linuksie tar może dokonać dodatkowej kompresji utworzonego archiwum, korzystając z dwóch uruchamianych w sposób niewidoczny dla użytkownika programów: compress (opcja -Z) albo gzip (opcja -z. Nasz przykład pokazuje zdecydowaną przewagę gzip nad compress

Pamiętajmy, że jeżeli chcemy na przykład przejrzeć skompresowane archiwum, musimy to uwzględnić w wywołaniu, na przykład tar -tzf mojearch

Podsumowując podstawowa składnia polecenia tar jest następująca:

tar    opcje    nazwa_archiwum    plik

gdzie nazwa_archiwum to już istniejący plik archiwum, bądź taki co dopiero zamierzamy utworzyć, natomiast plik to obiekty, które mamy umieścić w archiwum. Może to być list katalogów (plików) oddzielonych spacjami.
Wskazany katalog jest archiwizowany wraz ze wszystkimi podkatalogami (rekurencyjnie). Należy pamiętać o prawach dostępu

Opcje polecenia tar dzieli się na dwie grupy: obowiązkowe i dodatkowe. Któraś z obowiązkowych opcji musi wystąpić zawsze. Opcje mogą być podawane bez znaku minus "-" przed nimi. Np. tar tfz archiwum jest równoważne tar -tfz archiwum.
W przypadku stosowania znaku minus kolejność opcji nie jest obojętna. Dotyczy to przede wszystkim opcji -f, która w zapisie łańcucha opcji powinna być zawsze na końcu, gdyż bezpośrednio za nią musi występować nazwa archiwum. Nie przestrzeganie tej zasady może dać nie zamierzone rezultaty. Dobrym zwyczajem jest podawanie opcji obowiązkowej jako pierwszej.

Problem kolejności wynika stąd, że opcja -f posiada własny argument, nazwę archiwum. Opcji o podanym charakterze jest więcej. Aby uniknąć niejednoznaczności, możemy zrezygnować ze skróconego zapisu opcji. Przykładowo zapis:

tar -f arch -cz kat2

oznacza archiwizowanie katalogu kat2 do nowo utworzonego (-c) pliku archiwum (skompresowanego za pomocą gzip - opcją z) o nazwie arch. Skrócony prawidłowy zapis tego samego polecenia będzie wyglądał tak:

tar -czf arch kat2

Zapis bez poprzedzającego znaku minus nie jest wrażliwy na kolejność opcji.
Jeżeli otrzymamy niespodziewany komunikat o błędzie lub tar wykonuje nieco inne działanie niż planowaliśmy - w pierwszej kolejności sprawdzamy, jakich opcji użyliśmy i w jakiej kolejności (zwłaszcza jeżeli stosujemy znak minus). W złożonych przypadkach zamiast tracić czas na tropienie niejednoznaczności składni, lepiej skorzystać z dłuższego, lecz jednoznacznego zapisu.
Opcje obowiązkowe są następujące:
-A       -   dołączenie istniejących plików (archiwów) .tar do naszego archiwum
-c       -   utworzenie nowego archiwum
-d       -   wyszukanie różnic pomiędzy archiwum, a rzeczywistym systemem plików
-t       -   wyświetlenie zawartości archiwum
-r       -   dodanie nowych plików do archiwum
-u       -   aktualizacja plików w archiwum
--delete -   usunięcie plików z archiwum
-x       -   rozpakowanie plików z archiwum
Wybrane opcje dodatkowe:
-f plik  -   użycie wskazanego pliku jako archiwum. Wskazany plik może być zwykłym lub specjalnym
-h       -   nie zapisuje dowiązań symbolicznych, lecz pliki, na które one wskazują
-k       -   przy rozpakowaniu istniejące pliki nie będą nad pisywane
-M       -   utworzenie archiwum wieloczęściowego
-N data  -   archiwizowanie tylko plików nowszych niż podana data
-W       -   weryfikacja archiwum po jego utworzeniu
-z       -   kompresja (dekompresja) archiwum programem gzip
-Z       -   kompresja (dekompresja) archiwum programem compress
-p       -   dearchiwizacja wszystkich informacji o prawach dostępu
Utwórzmy teraz archiwum na dysku:
# tar -czf archtest /home
tar: Removing leading '/' from absolute path names in the archive
[root@linux /root]# mkdir /rob
[root@linux /root]# cd /rob
[root@linux /rob]# tar -zxf /root/archtest
[root@linux /rob]# ls
home
[root@linux /rob]# ls -F home
crash1/   crash2/
[root@linux /rob]# cd ~
[root@linux /root]# tar -rf archtest /etc/passwd
tar: This does not look like a tar archive
tar: Skipping to next header
tar: Only read 5497 bytes from archive arch
tar: Error is not recoverable: exiting now
[root@linux /root]# tar -rzf archtest /etc/passwd
tar: Cannot update compressed archives
tar: Error is not recoverable: exiting now
[root@linux /root]# mv archtest archtest.gz
[root@linux /root]# gunzip archtest.gz
[root@linux /root]# tar -rf archtest /etc/passwd
tar: Removing leading '/' from absolute path names in the archive
[root@linux /root]# tar -tf archtest etc/passwd
etc/passwd
[root@linux /root]# cd /rob
[root@linux /rob]# tar -xf /root/archtest  */passwd
[root@linux /rob]# ls
etc   home
[root@linux /rob]# ls etc
passwd
[root@linux /rob]# cd ~
[root@linux /root]# rm archtest
rm: remove 'arch'? y
[root@linux /root]# rm -rf /rob
[root@linux /root]# _
Najpierw utworzyliśmy archiwum (plik archtest) zawierające katalog /home. Następnie utworzyliśmy roboczy katalog /rob i w nim rozpakowaliśmy archiwum. W katalogu /rob został odtworzony katalog home wraz z całym drzewem podkatalogów i plików. Następnie próbowaliśmy dodać (tar -rf oraz tar -rzf) do naszego archiwum plik /etc/passwd. Przekonaliśmy się, że (niestety) nie można zaktualizować skompresowanego archiwum. Zdekompresowaliśmy archiwum programem gunzip, ale wcześniej zmieniliśmy jego nazwę na archtest.gz, gdyż gunzip oczekuje przyrostka .gz. Gunzip działa w ten sposób, że plik archtest.gz jest zastępowany plikiem o usuniętym z nazwy przyrostku .gz. Do tak zdekompresowanego archiwum możemy bez trudu dodać plik /etc/passwd. Następnie ten pojedynczy plik rozpakowaliśmy z całego archiwum do katalogu /rob.
Na koniec usunęliśmy katalog /rob. Użyliśmy tu opcji -f (force), która umożliwiła nam uniknięcie uciążliwych potwierdzeń.

Rozpakowujemy archiwum (tar)

Rozpakujmy archiwum ze źródłami jądra. Archiwum to znajduje się na CD-ROM-ie w katalogu /kernel/2.0.35. Rozpakujemy je do katalogu /usr/src/:
# cdm
hdc: media changed
[root@linux /root]# cd /usr/src
[root@linux src]# ls -F
linux@     linux-2.0.36/     redhat/
[root@linux /root]# file linux
linux: symbolic link to linux-2.0.36
[root@linux src]# rm -f linux
[root@linux src]# ls -F
linux-2.0.36/  Redhat/
# tar -xzpvf /mnt/cdrom/kernel/2.0.35/linux-2.0.35.tar.gz
...
...
linux/Documentation/paride.txt
[root@linux src]# ls -F
linux     linux-2.0.36/     redhat/
[root@linux src]# du -sh linux
26M   linux
[root@linux src]# cd ~
[root@linux /root]# _
Do zamontowania CDROM wykorzystaliśmy zdefiniowany alias cdm. Przypomnijmy, że znak @ przy nazwie linux oznacza dowiązanie symboliczne i nie jest częścią nazwy pliku. Dodatkowo upewniliśmy się o tym jeszcze poleceniem file. Jako rezultat rozpakowania powstał katalog linux wraz z obszernym drzewem katalogów i plików (łącznie 26 MB).
Skorzystaliśmy tu z nowych opcji tar-a. Pierwsza (-p) zachowuje prawa dostępu oryginału. Druga (-v) umożliwia wizualizację rozpakowania plików (widzimy je na ekranie).
Zwróćmy uwagę na składnie polecenia tar. Podaliśmy tu pełną ścieżkę dostępu do archiwum, dzięki temu uniknęliśmy kopiowania pliku archiwum do bieżącego katalogu.
Poznaliśmy kolejne dwie opcje polecenia du. Opcja -s (summarize) wyświetla tylko podsumowanie objętości katalogu, bez wypisywania wszystkich jego składników, Opcja -h (human) podaje rozmiar w jednostkach czytelnych dla ludzi. :-)
Na koniec poznamy jeszcze siłę filtrów i potoków. Zażyczymy sobie określenia liczby plików z dokumentacją zawartych w archiwum. Dla ułatwienia dodamy, że znajdują się one w katalogu archiwum: linux/Documentation.
# cd /mnt/cdrom/kernel/2.0.35
# tar -tzf *.tar.gz | grep "linux/Documentation" | wc -l
     98
[root@linux 2.0.35]# cd ~
[root@linux /root]# cdu
[root@linux /root]# _

Kompresujemy i dekompresujemy pliki (compress, uncompress, gzip, gunzip)

Tradycyjnym kompresorem w systemach uniksowych jest compress, tworzący skompresowane pliki z przyrostkiem .Z w nazwie. W Linuksie compress jest wypierany przez wydajniejszy gzip (GNU zip). Gzip potrafi rozpakować archiwa utworzone przez compress, natomiast swoim archiwom nadaje przyrostek .gz.
Do dekompresji skompresowanych plików używamy odpowiednio uncompress i gunzip, chociaż użycie gunzip można traktować jako zabieg formalny, gdyż dekompresji można dokonać także przez gzip wywołując go z opcją -d
Omawiane tu kompresory domyślnie działają nieco inaczej niż kompresory znane nam z DOSa. Przede wszystkim kompresują tylko pojedyncze pliki. Uruchomienie rekurencyjnej kompresji katalogu (opcja -r) spowoduje niezależne skompresowanie wszystkich plików w drzewie katalogu, ale nie zostanie utworzone archiwum w postaci jednego pliku. Takie archiwa możemy tworzyć za pomocą tar. Ogólnie compress i gzip nie tworzą żadnych archiwów, zamieniają po prostu wskazane pliki na pliki skompresowane. Określenie "zamieniają" należy traktować dosłownie, gdyż poddany kompresji plik zostanie zamieniony na skompresowany plik .Z, podczas gdy plik zostanie usunięty. Analogicznie sytuacja będzie wyglądała przy dekompresji: plik.Z zostanie zamieniony na plik plik, a plik plik.Z zostanie usunięty.
$ cp /etc/passwd  spak1
[crash1@linux crash1]$ cp /bin/bash  spak2
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1   spak2*
[crash1@linux crash1]$ compress *
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1.Z   spak2.Z*
[crash1@linux crash1]$ ls bin
zmk
[crash1@linux crash1]$ uncompress -c spak2.Z | wc -c
353944
[crash1@linux crash1]$ zcat  spak2.Z | wc -c
353944
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1.Z   spak2.Z*
[crash1@linux crash1]$ uncompress *1.Z
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1   spak2.Z*
[crash1@linux crash1]$ uncompress -v spak2.Z
spak2.Z:   -- replace with spak2
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1   spak2*
[crash1@linux crash1]$ compress -rv .
./.Xdefaults: -- replaced with ./Xdefaults.Z  Compression: 32.64%
./.bash_logout: No compression -- ./.bash_logout unchanged
...
...
./.spak1: -- replaced with ./spak1.Z  Compression: 30.22%
./.spak2: -- replaced with ./spak2.Z  Compression: 43.12%
[crash1@linux crash1]$ ls kat2
costutaj.Z itennasz.Z naszplik.Z naszplik1.Z naszplik2.Z
[crash1@linux crash1]$ uncompress -r  .
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1   spak2*
[crash1@linux crash1]$ _
Przetrenowaliśmy compress (uncompress) poznając jego wiele opcji. Zwróćmy uwagę na wykorzystanie potoku (z poleceniem wc -c) do znalezienia rozmiaru nieskompresowanego pliku (czyli policzenia jego bajtów) na podstawie pliku skompresowanego. Potok ów zrealizowany został na dwa sposoby: raz za pomocą uncompress, drugi raz za pomocą zcat. Polecenie zcat działa analogicznie jak cat, z tym że operuje na plikach skompresowanych. Dzięki poleceniu zcat możemy szybko obejrzeć skompresowany plik tekstowy bez potrzeby jego dekompresji. Polecenie to nie wymaga żadnych określonych przyrostków w nazwie pliku - weryfikuje plik tylko na podstawie treści nagłówka, a ściślej sprawdza tzw. magiczną liczbę.
Polecenie uncompress oczekuje przyrostka .Z w nazwie pliku, ale sprawdza również jego format w treści nagłówka (magiczna liczba). Obydwa warunki muszą być spełnione, aby dekompresja doszła do skutku.
Przy rekurencyjnej kompresji (-r) z wizualizacją (-v) pokazaliśmy tylko dwa pierwsze i dwa ostatnie wiersze listingu monitorowego. Zwróćmy uwagę, że archiwizowane są wszystkie pliki i katalogi, także te ukryte.
Gwiazdka "*" w listingu polecenia ls umieszczona za nazwą pliku spak2, nie jest częścią nazwy tego pliku. Lecz wskazuje nam, że jest to plik wykonywalny.
Wybrane opcje polecenia compress (uncompress):
-c   -  zapisuje plik wyjściowy na standardowe wyjście, nie modyfikując pliku wejściowego.
-v   -  (verbose) wizualizacja (raport na ekranie), zarówno kompresji, jak i dekompresji.
-r   -  (recursively) kompresij (dekompresuj) rekurencyjnie
A teraz kilka przykładów z gzip:
$gzip spak2
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1   spak2.gz*
[crash1@linux crash1]$ gzip -dv  *
gzip:  bin is a directory  -- ignored
gzip: kat2 is a directory  -- ignored
gzip: spak1: unkown suffix  -- ignored
spak2.gz:                      57.9%  -- replaced with spak2
[crash1@linux crash1]$ gzip  *
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1.gz   spak2.gz*
[crash1@linux crash1]$ gzip -cd  spak2.gz | wc -c
353944
[crash1@linux crash1]$ mv spak1.gz spak1.abc
[crash1@linux crash1]$ gunzip spak1.abc
gunzip: spak1.abc: unkown suffix  -- ignored
[crash1@linux crash1]$ gunzip -S  .abc  spakl.abc
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1   spak2.gz*
[crash1@linux crash1]$ mv spak1 spak1.gz
[crash1@linux crash1]$ gunzip spak1.gz

gunzip: spak1.gz: not in gzip format
[crash1@linux crash1]$ mv spak1.gz  spak1
[crash1@linux crash1]$ gunzip -lv  spak2.gz
metod crc      date   time   compressed   uncompr.  ratio
                                                    uncompressed_name
delfa a57da665 May 29 07:19  1489878      353944    57.9%   spak2
[crash1@linux crash1]$ gzip -S .bcd  spak1
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1.bcd   spak2.gz*
[crash1@linux crash1]$ gunzip -S .bcd  spak1.bcd
[crash1@linux crash1]$ gunzip spak2.gz
[crash1@linux crash1]$ ls -F
bin/  kat2/  spak1.bcd   spak2*
[crash1@linux crash1]$ rm spak1
[crash1@linux crash1]$ _
Cechą szczególną gzip-a jest opcja -S służąca do manipulowania przyrostkami. Ma to znaczenie, gdy przenosimy skompresowane pliki pomiędzy różnymi systemami operacyjnymi, w których stosowane przyrostki (rozszerzenia) mogą być różne.
Analogicznie jak compress, program gunzip oczekuje określonego (domyślnie .gz) przyrostka, ale identyfikuje skompresowany plik zarówno po przyrostku, jak i na podstawie treści nagłówka (magiczna liczba). Nie będzie zatem próbował dekompresować pliku, który posiada jedynie właściwy przyrostek.
Poniżej przedstawiamy wybrane opcje polecenia gzip (gunzip). Trzy pierwsze są takie same jak dla compress (uncompress). Opis ten umożliwi nam samodzielną analizę dotychczasowych działań z gzip-em:
-c   -  zapisuje plik wyjściowy na standardowe wyjście, nie modyfikując pliku wejściowego.
-v   -  (verbose) wizualizacja (raport na ekranie), zarówno kompresji, jak i dekompresji.
-r   -  (recursively) kompresji (dekompresuj) rekurencyjnie
-l   -  (list) raport dotyczący rozmiaru już skompresowanych plików.
-t   -  testuje spójność skompresowanego pliku
-d   -  dekompresja
-S .przyrostek  -  zastosuj wskazany .przyrostek
-n   -  liczna (od 1 do 9) określająca wydajność kompresji, domyślnie n=6.
Sprawdźmy domyślne i skrajne (dla n=1 i n=9) możliwości kompresji:
$ gzip spak2 ;  gunzip -v spak2.gz
spak2.gz                                    57.9% -- replaced with spak2
[crash1@linux crash1]$ gzip -1  spak2 ; gunzip -v spak2.gz
spak2.gz                                    53.7% -- replaced with spak2
[crash1@linux crash1]$ gzip -9  spak2 ; gunzip -v spak2.gz
spak2.gz                                    58.0% -- replaced with spak2
[crash1@linux crash1]$ rm spak2
[crash1@linux crash1]$ _
Przypomnijmy, że średnik jest separatorem poleceń wiersza. Jak widzimy, domyślna wartość n=6 jest sensownym kompromisem pomiędzy szybkością a wydajnością.

Tworzymy i montujemy łaty (diff, patch)

Diff jest zaawansowanym narzędziem do porównywania plików. Jest to program o bardzo rozbudowanych możliwościach. Jego podstawową zaletą jest zaletą jest tworzenie pliku różnicowego jako wyniku porównywania dwóch plików. Dysponując plikiem różnicowym i jednym z porównywanych plików można odtworzyć drugi plik. Służy do tego polecenie patch. Mechanizm ten jest używany w Linuksie do aktualizacja tekstów źródłowych oprogramowania. Stosowana w tej sytuacji terminologia to łata i łatanie.
Zalety łat widać jak na dłoni. Ściągnięcie przez Internet nowej pełnej wersji źródeł jądra systemu może być problemem, gdyż jest to plik o rozmiarze rządu 25 MB. Tymczasem typowa łata będzie znacznie mniejsza, na przykład rzędu 500 kB albo nawet mniej.
Plik różnicowy może być generowany w różnych formatach. Typowym jest "GNU unified" (opcja -u). Argumentami polecenia diff mogą być dwa pliki lub dwa katalogi. W przypadku katalogów diff będzie porównywał odpowiednie pliki w obu katalogach w kolejności alfabetycznej. Porównanie takie domyślnie nie jest rekurencyjne. Rekurencyjność możemy uzyskać stosując opcję -r.
W celu wykonania przykładów utworzymy za pomocą cat (lub vi) w katalogu domowym użytkownika dwa pliki tekstowe. Pierwszy o nazwie plik1.1 i zawartości:
Ala ma kota.
i drugi o nazwie plik1.2 i treści:
Ala ma kota i psa.
W naszym przykładzie plik1.2 będziemy traktować jak zmodyfikowaną (nowszą) wersję plik1.1:
$ mkdir rob
[crash1@linux crash1]$ ls -F
bin/  kat2/  plik1.1  plik1.2  rob/
[crash1@linux crash1]$ diff -u plik1.1  plik1.2 > lata1.1do1.2
[crash1@linux crash1]$ cat lata1.1do1.2
---  plik1.1           Sun May 30  11:01:45 2000
+++  plik1.2           Sun May 30  11:02:43 2000
@@ -1 +1 @@
-Ala ma kota.
+Ala ma kota i psa.
[crash1@linux crash1]$ diff -c plik1.1 plik1.2 > lata1.1do1.2c
[crash1@linux crash1]$ cat lata1.1do1.2
***  plik1.1           Sun May 30  11:01:15 2000
---  plik1.2           Sun May 30  11:02:43 2000
*************
*** 1 ***
! Ala ma kota.
--- 1 ---
! Ala ma kota i psa.
[crash1@linux crash1]$ mv lat* rob
[crash1@linux crash1]$ cp plik1.1 rob ; cd rob
[crash1@linux rob]$ ls
lata1.2do1.2  lata1.do1.2c  plik1.1
[crash1@linux rob]$ patch < lata1.1do1.2
patching file `plik1.1'
[crash1@linux rob]$ cat plik1.1
Ala ma kota i psa.
[crash1@linux rob]$ cp ../plik1.1
[crash1@linux rob]$ patch < lata1.1do1.2c
patching file `plik1.1'
[crash1@linux rob]$ cat plik1.1
Ala ma kota i psa.
[crash1@linux rob]$ _
Widzimy, że diff może tworzyć pliki wynikowe w różnych formatach w zależności od podanej opcji:
-u  -  format GNU unified
-c  -  trzywierszowy kontekst wokół każdej różnicy.
Jak zauważyliśmy, patch automatycznie rozpoznaje format pliku różnicowego. Po założeniu łaty treść pliku plik1.1 odpowiada treści pliku plik1.2. Zwróćmy uwagę na składnię polecenia patch. Będzie ono szukało pliku do łatania znajdującego się w bieżącym katalogu.
Wykonamy teraz przykład z porównywaniem katalogów, ale najpierw przygotujemy dwa ćwiczebne katalogi:
$ cd ~
[crash1@linux crash1]$ rm  -rf rob
[crash1@linux crash1]$ mkdir rob1 rob2
[crash1@linux crash1]$ cp plik*  rob2 ; cd rob1
[crash1@linux rob1]$ touch plik1.1 plik1.2 ; cd ~
[crash1@linux crash1]$ du -b rob1/*  rob2/*
0      rob1/plik1.1
0      rob1/plik1.2
13     rob2/plik1.1
19     rob2/plik1.2
[crash1@linux crash1]$ _
Mamy zatem dwa katalogi zawierające pliki o tych samych nazwach, ale w rob1 są pliki puste, a w rob2 z dotychczasowym tekstem. Potraktujmy rob2 jak nowszą wersję rob1, sporządźmy łatę do aktualizacji rob1, a następnie załóżmy ją:
# diff -u rob1  rob2 > lata1do2
[crash1@linux crash1]$ cat lata1do2
diff -u rob1/plik1.1 rob2/plik1.1--- rob1/plik1.1
Sun May 30  12:31:15 2000+++ rob2/plik1.1
Sun May 30  12:32:43 2000@@@ -0,0 +1 @@+Ala ma kota.diff -u
rob1/plik1.2 rob2/plik1.2--- rob1/plik1.2
Sun May 30  12:33:15 2000+++ rob2/plik1.2
Sun May 30  12:35:43 2000@@@ -0,0 +1 @@+Ala ma kota i psa.
[crash1@linux crash1]$ patch -p0 < lata1do2
patching file `plik1.1'
patching file `plik1.2'
[crash1@linux crash1]$ du -b rob1/*  rob2/
13     rob1/plik1.1
19     rob1/plik1.2
13     rob2/plik1.1
19     rob2/plik1.2
[crash1@linux crash1]$ mkdir rib3 ; touch plik1.1 plik1.2
[crash1@linux crash1]$ cd rob3
[crash1@linux rob3]$ patch < ../lata1od2
patching file `plik1.1'
patching file `plik1.2'
[crash1@linux rob3]$ du -b *
13     plik1.1
19     plik1.2
[crash1@linux rob3]$ patch -R < ../lata1do2
patching file `plik1.1'
patching file `plik1.2'
[crash1@linux rob3]$ du -b *
0      plik1.1
0      plik1.2
[crash1@linux rob3]$ cd ~
[crash1@linux crash1]$ rm -rf rob* ; rm lat* plik*
[crash1@linux rob3]$ _
Opcja -p0 służy do użycia nie zmienionych ścieżek dostępu do plików, czyli takich, jakie są zapisane w pliku lata1do2. Domyślnie bowiem patch będzie aktualizował pliki znajdujące się w bieżącym katalogu. Opcja -p0 pozwala na wywołanie patch-a z poziomu katalogu rodzicielskiego w stosunku do katalogu, który będzie aktualizowany.
Wywołanie patch bez tej opcji spowoduje załatanie bieżącego katalogu. Wreszcie poznaliśmy bardzo użyteczną opcję -R umożliwiającą zdjęcie łaty, czyli przywrócenie pierwotnej treści plików. Opcja -R będzie skuteczna tylko z plikami różnicowymi wygenerowanymi w formacie, który zawiera informacje wystarczające do odwrócenia poprzedniej operacji patch. Jak widzimy, format GNU unifed zdaje tu egzamin.