LINUXSOFT.cz Přeskoč levou lištu

ARCHIV



   

> Linux v příkazech - porovnávání souborů

Rozebereme metody porovnávání souborů, mergování a vytváření a aplikace patchů.

28.3.2006 06:00 | Jiří Václavík | Články autora | přečteno 37832×

Historie nástrojů pro porovnávání obsahu textových souborů se píše již několik desítek let. Hlavními zástupci této kategorie nástrojů jsou diff a patch. diff hledá rozdíly ve dvou souborech a vytváří záplaty, které umí aplikovat inverzní příkaz patch.

Prosté porovnání

Asi nejjednodušším programem z této sady je cmp. Porovná 2 soubory, a jestliže se liší, vypíše kolikátý je první odlišný bajt. S přepínačem --print-bytes vypíše i tento odlišný znak. Jsou-li soubory shodné, cmp neprodukuje žádný výstup.

$ cmp soubor1 soubor2
soubor1 soubor2 differ: char 152, line 12
$

Pro tento účel lze použít i příkaz diff s parametrem -q.

Podrobné porovnání

Složitějším a značně pokročilejším příkazem pro porovnávání je diff. Neporovnává systémem znak po znaku, ale hledá společné a rozdílné části souborů. Příkaz diff už není pouze nástrojem pro získání informace, zda se soubory liší, ale zjišťuje v čem se liší.

diff také umí do jisté míry omezit, jaké rozdíly mezi soubory má zobrazit. Je schopen rozeznat například to, že se soubory liší pouze prázdnými řádky. Mezi další vlastnosti příkazu diff patří podpora několika výstupních formátů a schopnost pracovat s regulárními výrazy.

Ve výstupu příkazu diff se objevují rozdílné řádky z obou porovnávaných souborů, které jsou doprovázeny příslušnými značkami podle formátu zobrazení a typu rozdílnosti.

Abychom si mohli vlastnosti nástroje diff předvést na konkrétních příkazech, vytvoříme si dva soubory - original s obsahem

Jedno nedělní dopoledne, když se zvířata shromáždila, aby vyslechla
příkazy, oznámil Napoleon, že se rozhodl pro novou hospodářskou politiku.
Od nynějška bude farma zvířat obchodovat se sousedními farmami.
Pochopitelně, že ne za komerčním účelem, ale jen proto, aby mohla získat
nejpotřebnější materiál. Větrný mlýn musí stát nad vším ostatním, řekl.

a následně soubor zmeneny:

Jedno nedělní dopoledne, když se zvířata shromáždila, aby vyslechla
příkazy, oznámil Napoleon, že se rozhodl pro novou hospodářskou politiku.
Od nynějška bude Farma zvířat obchodovat se sousedními farmami.
Pochopitelně, že ne za komerčním účelem, ale jen proto, aby mohla získat
nejpotřebnější materiál. Větrný mlýn musí stát nad vším ostatním, řekl.

Text byl převzat z knihy Farma zvířat.

Nyní zkusme najít všechny rozdíly v obou souborech. Srovnávání ručně znak po znaku je pomalé a navíc nejisté. Použijeme diff.

Máme k dispozici hned několik formátů výstupu.

Implicitní formát

Výstup porovnávání souborů original a zmeneny v implicitním formátu má následující strukturu:

změna
< řádek z 1. souboru
< řádek z 1. souboru
---
> řádek z 2. souboru
> řádek z 2. souboru
...

Změna obsahuje tři údaje a určuje místo v souboru, ve kterém byly nalezeny odlišnosti. První resp. třetí údaj určují příslušné řádky v prvním resp. druhém souboru a mohou obsahovat čísla řádků nebo rozsahy. Druhý údaj popisuje typ změny, který může nabývat tří hodnot:

ZnakVýznam
aV prvním souboru chybí dané řádky
cV souborech se liší dané řádky
dV prvním souboru jsou dané řádky navíc

Nyní příkaz diff zavoláme již s konkrétními parametry.

$ diff original zmeneny
3c3
< Od nynějška bude farma zvířat obchodovat se sousedními farmami.
---
> Od nynějška bude Farma zvířat obchodovat se sousedními farmami.
$

Okamžitě vidíme, na kterém řádku je rozdíl.

Kontextový formát

Zejména v rozdílech zdrojových souborů uvítáme další formát výpisu změn. Přidáme-li přepínač -C s celočíselnou hodnotou, diff zobrazí okolo změn i daný počet okolních řádků.

$ diff -C1 original zmeneny
*** zmeneny   2006-03-12 16:07:39.000000000 +0100
--- original  2006-03-12 14:02:38.000000000 +0100
***************
*** 2,4 ****
  příkazy, oznámil Napoleon, že se rozhodl pro novou hospodářskou politiku.
! Od nynějška bude Farma zvířat obchodovat se sousedními farmami.
  Pochopitelně, že ne za komerčním účelem, ale jen proto, aby mohla získat
--- 2,4 ----
  příkazy, oznámil Napoleon, že se rozhodl pro novou hospodářskou politiku.
! Od nynějška bude farma zvířat obchodovat se sousedními farmami.
  Pochopitelně, že ne za komerčním účelem, ale jen proto, aby mohla získat
$

Výstup začíná hlavičkami, za nimiž je část, z níž je patrné, v čem se oba texty liší. Každý řádek textu na výstupu začíná buď mezerou, znakem +, znakem - nebo vykřičníkem. Mezery značí shodné řádky a znaménka ty odlišné. Čísla uvozená znaky *** resp. --- znamenají rozsahy řádků pro příslušný soubor.

Sjednocený kontextový formát

Zaměníme-li -C za -U, nebude docházet k případnému opakovanému výstupu týchž řádků. Abychom spatřili rozdíl, musíme pozměnit ještě jiný řádek 2. souboru.

$ diff -U1 original zmeneny
--- original  2006-03-12 17:07:37.000000000 +0100
+++ zmeneny   2006-03-12 17:07:39.000000000 +0100
@@ -2,3 +2,3 @@
 příkazy, oznámil Napoleon, že se rozhodl pro novou hospodářskou politiku.
-Od nynějška bude Farma zvířat obchodovat se sousedními farmami.
-Pochopitelně, že ne za komerčním účelem, ale jen proto, aby mohla získat
+Od nynějška bude farma zvířat obchodovat se sousedními farmami.
+Pochopitelně, že ně za komerčním účelem, ale jen proto, aby mohla získat
 nejpotřebnější materiál. Větrný mlýn musí stát nad vším ostatním, řekl.
$

Sloupcový formát

Dále lze porovnávat soubory také ve sloupcích. Značky pro upozornění na rozdíly jsou pak mezi oběma sloupci. Výstup je velmi široký, což je značná nevýhoda. Pomocí přepínače -W lze řádky useknout na požadovanou délku.

$ diff -y -W80 original zmeneny
Jedno nedělní dopoledne, když se zvíř   Jedno nedělní dopoledne, když se zvíř
příkazy, oznámil Napoleon, že se rozh   příkazy, oznámil Napoleon, že se rozh
Od nynějška bude Farma zvířat obchodo | Od nynějška bude farma zvířat obchodo
Pochopitelně, že ně za komerčním účel   Pochopitelně, že ně za komerčním účel
nejpotřebnější materiál. Větrný mlýn    nejpotřebnější materiál. Větrný mlýn
$

Porovnávání adresářů

Je-li jeden ze souborů předaných příkazu diff adresářem, hledá se v tomto adresáři soubor se stejným názvem jako uvedený textový soubor a ten se potom také porovnává. S přepínačem -r lze hledat v adresáři rekurzivně.

Nyní zadáme oba parametry jako názvy adresářů. Adresáře budou obsahovat tyto soubory:

$ ls verze0-98
soubor1  soubor2 soubor3 souborx
$ ls verze0-99
soubor1  soubor2 soubor3 soubory
$

Pomocí diff tyto adresáře porovnáme.

$ diff verze0-98 verze0-99
diff verze0-98/soubor2 verze0-99/soubor2
1c1
< obsah1
---
> obsah2
Pouze v verze0-98: souborx
Pouze v verze0-99: soubory
$

Vidíme, že se liší soubory verze0-98/soubor2 a verze0-99/soubor2 a rozdíly mezi nimi jsou zobrazeny. Navíc souborx je pouze v adresáři verze0-98 a soubory jen v verze0-99. V případě, že budeme chtít vypsat i změny souborů, které jsou pouze v jednom adresáři (například pro vytvoření patche), přidáme přepínač -N. Přidáním -r se bude porovnávat rekurzivně.

Další vlastnosti

Předáme-li příkazu diff přepínač -b, bude tolerovat odlišnosti v počtu mezer a tabulátorů a bude též ignorovat mezery na koncích řádků.

Pokud připíšeme -B, budou se ignorovat také odlišnosti výplývající z vložených prázdných řádků. Jsou-li však na řádku mezery nebo tabulátory, není brán jako prázdný. Abychom ignorovali i tyto řádky, musíme kromě -B použít i přepínač -b.

Přepínač -l připraví stránku pro tisk za pomoci příkazu pr.

Příkaz diff obsahuje také dvě volby ovlivňující rychlost hledání. -d zapíná důkladnější, ale také pomalejší hledání rozdílů. Rozdíly tak budou logičtěji uspořádané. Porovnáváme-li velké soubory, které se liší jen nepatrně, bude diff efektivnější s přepínačem -H.

diff podporuje regulární výrazy. Lze tak například omezit odlišnosti pouze na řádky, které nevyhovují danému regulárnímu výrazu. Pokud nebudeme chtít hlášení o řádcích, které končí číslicí, zadáme:

$ diff -I '[[:digit:]]$' original zmeneny

Vytváření patchů

Patch je souborem, obvykle s příponou .diff, který obsahuje seznam změn, jež je třeba provést, abychom z originálního souboru získali soubor změněný. Je to tedy jakýsi postup úprav.

Patch je mimo jiné cesta, jak distribuovat nové nebo upravené verze programů mezi vývojáři. Mají-li všichni vývojáři původní soubor (ve kterém mohou mít svoje drobné změny) a někdo z vývojářů chce svoji úpravu poskytnout ostatním, obvykle místo celého souboru pošle jen seznam změn, které udělal - tedy patch.

Vytvoříme patch pro upravení souboru original podle souboru zmeneny. .diff soubor získáme příkazem:

$ diff original zmeneny > change.diff

Pro vytváření patchů z více souborů se používá následující příkaz:

$ diff -Nr dir1 dir2 > change.diff

Po vytvoření patche je užitečné zobrazit si ho v textovém editoru a zkontrolovat, zda neobsahuje nějaké zbytečné úpravy jako je přidání bílých znaků. Pokud tyto změny obsahuje, měli bychom je zrušit a vygenerovat patch znovu.

Náš .diff soubor opravuje velikost úvodního písmena ve slově farma.

$ cat change.diff
3c3
< Od nynějška bude farma zvířat obchodovat se sousedními farmami.
---
> Od nynějška bude Farma zvířat obchodovat se sousedními farmami.
$

Aplikace patchů

Pro aplikaci patche se používá příkaz patch. patch aplikuje .diff soubor na originální soubor.

Z minulého oddílu již máme vytvořený soubor change.diff, který nyní aplikujeme na soubor original. Následkem toho ve slově farma opravíme písmeno f na velké.

$ patch original change.diff
patching file original
$

Pokud je již v patchi uvedeno jméno původního souboru (patch musí používat nějaký formát, který jméno souboru uchovává), lze psát i

$ patch < change.diff

Vždy, když patch neví jak postupovat dále, zeptá se.

Ještě před aplikací patche se vytvoří záloha v podobě původního souboru s příponou implicitně .orig, která se dá změnit přepínačem -b.

Když máme vytvořen patch opačně - tj. ze změněného souboru na originální, máme k dispozici soubor originální a potřebujeme vytvořit soubor změněný, aplikujeme patch reverzně pomocí přepínače -R. Většinou však sám patch pozná, že aplikujeme opačný patch a zeptá se, zda ho má použít reverzně.

Problémy při aplikaci mohou nastat, pokud dojde k záměně mezer a tabulátorů. V takovém případě je třeba zadat -l pro ignorování bílých míst.

Pokud nelze z nějakého důvodu záplatu aplikovat, zálohuje se do .rej souboru.

Porovnání tří souborů

V případě, kdy dva lidé změní tentýž soubor a obě změny chceme promítnout ve výsledném patchi, použijeme diff3. U tohoto nástroje uveďme pouze příklad, takže případní zájemci se podívají na manuálovou stránku.

Pro ukázku vytvoříme dva soubory lišící se od originálu, který již máme. Soubor zmeneny1:

Jedno nedělní dopoledne, když se zvířata shromáždila, aby vyslechla
příkazy, oznámil Napoleon, že se rozhodl pro novou hospodářskou politiku.
Od nynějška bude farma zvířat obchodovat se sousedními farmami.
Pochopitelně, že ne za komerčním účelem, ale jen proto, aby mohla získat
ZMENA2nejpotřebnější materiál. Větrný mlýn musí stát nad vším ostatním, řekl.

A soubor zmeneny2:

Jedno nedělní dopoledne, když se zvířata shromáždila, aby vyslechla
příkazy, oznámil Napoleon, že se rozhodl pro novou hospodářskou politiku.
Od nynějška bude farma zvířat obchodovat se sousedními farmami.
Pochopitelně, že ne za komerčním účelem, ale jen proto, aby mohla získat
ZMENA3nejpotřebnější materiál. Větrný mlýn musí stát nad vším ostatním, řekl.

Nyní zobrazíme změny:

$ diff3 zmeneny1 original zmeneny2
====2
1:3c
3:3c
  Od nynějška bude farma zvířat obchodovat se sousedními farmami.
2:3c
  Od nynějška bude Farma zvířat obchodovat se sousedními farmami.
====
1:5c
  ZMENA2nejpotřebnější materiál. Větrný mlýn musí stát nad vším ostatním, řekl.
2:5c
  nejpotřebnější materiál. Větrný mlýn musí stát nad vším ostatním, řekl.
3:5c
  ZMENA3nejpotřebnější materiál. Větrný mlýn musí stát nad vším ostatním, řekl.
$

Změny jsou od sebe ve výpisu vždy odděleny řetězcem ====. Za ním může být pořadí odlišného souboru, jsou-li ostatní dva stejné. V každém oddílu jsou 3 řádky (pro každý soubor jeden) ve formátu pořadí_souboru:řádky a tyto řádky jsou vzápětí vypsány.

Hledání odlišných slov

Další a mnohdy přehlednéjší možností, jak zobrazovat rozdíly mezi soubory je wdiff. wdiff hledá nikoliv řádky, ale slova, ve kterých se soubory liší. Obecně lze říci, že slovo je nenulová posloupnost znaků mezi dvěma bílými znaky. Odlišnosti v bílých znacích jsou ignorovány. V praxi může použití wdiff vypadat takto:

$ wdiff original zmeneny
Jedno nedělní dopoledne, když se zvířata shromáždila, aby vyslechla
příkazy, oznámil Napoleon, že se rozhodl pro novou hospodářskou politiku.
Od nynějška bude [-farma-] {+Farma+} zvířat obchodovat se sousedními farmami.
Pochopitelně, že ne za komerčním účelem, ale jen proto, aby mohla získat
nejpotřebnější materiál. Větrný mlýn musí stát nad vším ostatním, řekl.
$

Slova, která jsou navíc v souboru original jsou ve výstupu implicitně uvozeny znaky [- a -] a slova, jež naopak v tomto souboru nejsou, znaky {+ a +}. Uvození lze změnit uvedením přepínačů -w, -x, -y a -z. Další možností je zapnuté zvýrazňování pomocí -t.

Lze též využít přepínačů -1 a -2, které zobrazují změny pouze jednostranně. Chceme-li zobrazit jen odlišná slova bez textu okolo, použijeme přepínač -3. Tyto přepínače lze kombinovat.

$ wdiff -3 original zmeneny
======================================================================
 [-farma-] {+Farma+}
======================================================================
$

Pro zobrazení statistik zahrnujících počty společných a odlišných slov připišme přepínač -s.

Mergování

Mergování, nebo-li slučování dvou souborů, se provádí příkazem sdiff. sdiff je příkaz s interaktivním rozhraním, který postupně prochází řádky obou souborů a při konfliktech se uživatele ptá, jak postupovat dále. Výsledkem po sdiff je soubor sloučený ze dvou souborů původních.

Budeme-li chtít vytvořit soubor vysledek sloučením souborů pravy a levy, použijeme toto volání příkazu sdiff:

$ sdiff -o vysledek pravy levy

V případě, že dojde k nějakým nejasnostem, budeme příkazem sdiff dotazováni, co se změnami. Máme tyto možnosti, jak odpovídat:

PříkazVýznam
rvybere variantu z pravého souboru
lvybere variantu z levého souboru
evlastní řádek
ebvlastní řádek, do editoru budou předvloženy pravý a levý řádek
elvlastní řádek, do editoru bude předvložen levý řádek
ervlastní řádek, do editoru bude předvložen pravý řádek
qkonec

U příkazů, které začínají na e je třeba mít nastavenu proměnnou prostředí $EDITOR, kde je uloženo jméno editoru, ve kterém budou řádky upravovány.

GUI nadstavby

Mezi GUI nástroje, které se používají pro porovnávání a mergování souborů patří TkDiff.

TkDiff

Uživatelé KDE asi budou znát také Kompare.

Kompare

Další zdroje

Verze pro tisk

pridej.cz

 

DISKUZE

Chybí mi tu.. 28.3.2006 10:23 Aleš Kapica
defaultni format diff? 29.3.2006 00:40 Stepan Roucka
L Re: defaultni format diff? 29.3.2006 13:40 Jiří Václavík
  L Re: defaultni format diff? 29.3.2006 13:43 o.k.
patche 29.3.2006 15:33 Aleš Hakl




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

28.11.2018 23:56 /František Kučera
Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1

12.11.2018 21:28 /Redakce Linuxsoft.cz
22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář

6.11.2018 2:04 /František Kučera
Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

4.10.2018 21:30 /Ondřej Čečák
LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář

18.9.2018 23:30 /František Kučera
Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

9.9.2018 14:15 /Redakce Linuxsoft.cz
20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business. Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář

12.8.2018 16:58 /František Kučera
Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář

16.7.2018 1:05 /František Kučera
Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

31.7.2023 14:13 / Linda Graham
iPhone Services

30.11.2022 9:32 / Kyle McDermott
Hosting download unavailable

13.12.2018 10:57 / Jan Mareš
Re: zavináč

2.12.2018 23:56 / František Kučera
Sraz

5.10.2018 17:12 / Jakub Kuljovsky
Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2024) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze