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 kat2oznacza 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 kat2Zapis 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ą
-dOmawiane
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.