Linux: Kniha kouzel, 2.15 (1. března 2025)
Veškerá moc příkazové řádky/příkazového řádku přehledně, pro začátečníky i pokročilé

29. Zpracování binárních souborů

Vývoj vanilkové příchuti Linuxu: Knihy kouzel byl 1. března 2025 ukončen. Tento text je zachován jako historický, ale chyby již nejsou opravovány. Odnože projektu pod kompatibilní licencí jsou vítány.

1. Úvod

Tato kapitola uvádí příkazy k analýze, zpracování a úpravě souborů bez jakéhokoliv ohledu na formát jejich obsahu. Jde o zpracování souboru jako celek, zpracování po jednotlivých bajtech nebo po blocích pevné velikosti.

Předmětem této kapitoly není šifrování dat, elektronické podepisování, komprese ani ukládání souborů do archivů či vybalování z nich.

Nástroje od, strings, *sum, split a některé další jsou vyvíjeny v rámci projektu GNU. Nástroj xxd není vyvíjen v rámci projektu GNU.

2. Definice

  • Velikost-P je počet bajtů, který může obsahovat (a často obsahuje) multiplikativní příponu K, M, G, T, P pro mocniny 1024 (kibibajty, mebibajty atd.) nebo kB, MB, GB, TB, PB (kilobajty, megabajty atd.) pro mocniny 1000. Takže máte-li do příkazu zadat velikost-P, čtyři mebibajty můžete zadat jako „4194304“ nebo jako „4M“ (což je podstatně snazší a přehlednější).
  • Heš („hash“, „hash code“, někdy méně přesně „kontrolní součet“) je číslo (obvykle v hexadecimálním tvaru) vypočítané z určitých binárních dat pomocí hešovací funkce.

3. Zaklínadla: Soubor jako celek

3/1 Vypsat obsah souboru pro člověka

@vypsat hexadecimálně#1
xxd [-c bajtů-na-řádek] [-g bajtů-na-skupinu] [-s počáteční-adresa] [-l max-počet-bajtů] [-u] soubor [| less]
@vypsat binárně#2
xxd -b [-c bajtů-na-řádku] [-s počáteční-adresa] [-l max-počet-bajtů] soubor [| less]
@najít v binárním souboru čitelné textové řetězce a vypsat je#3
strings [-f] [-n minimální-délka-řetězce] [--] soubor
@vypsat osmičkově#4
od -A x -t o1z [-wbajtů-na-řádku] [-j počáteční-adresa] [-N max-počet-bajtů] -- [soubor] [| less]
@vypsat hodnoty bajtů desítkově#5
od -A x -t u1z [-wbajtů-na-řádku] [-j počáteční-adresa] [-N max-počet-bajtů] -- [soubor] [| less]

3/2 Vypočítat a ověřit heš

@vypočítat hexidecimální haše souborů, každou hash na nový řádek (MD5/SHA1/SHA256/SHA512)#1
md5sum [--] soubor | sed -E 's/^\\?(\S+)\s.*/\1/'⊨ 8147f2a49ee708d9f7c20164cf48cfcf
sha1sum [--] soubor | sed -E 's/^\\?(\S+)\s.*/\1/'⊨ c61d1871cf7d71f29e2cfeda9dd73abe18a8fb42
sha256sum [--] soubor | sed -E 's/^\\?(\S+)\s.*/\1/'
sha512sum [--] soubor | sed -E 's/^\\?(\S+)\s.*/\1/'
@vypočítat/ověřit heše (SHA256)#2 (1)
sha256sum soubor > cílový-soubor.sha256
sha256sum [--ignore-missing] [--status] -c soubor.sha256
@vypočítat/ověřit heše (MD5)#3 (2)
md5sum cesta > cílový-soubor.md5
md5sum [--ignore-missing] [--status] -c soubor.md5
@vypočítat kontrolní součet CRC32 (v hexadecimální soustavě/v desítkové)#4 (3)
crc32 soubor
printf %d\\n $((0x$(crc32 "soubor")))
@vypočítat z jednoho souboru heše (MD5) záznamů ukončených nulovým bajtem#5
perl -MEnglish -MDigest::MD5 -pe 'BEGIN {$RS = "\x{0}"; $ORS = "\n";} $ARG = Digest::MD5::md5_hex($ARG);' >soubor

3/3 Určit formát dat a velikost souboru

@popsat typ dat souboru (zejména pro člověka)#1
file soubor
@vypsat MIME typ souboru (vhodné i pro skript)#2
file [-b] [-L] --mime-type soubor
@určit velikost souboru v bajtech (alternativy)#3
wc -c [soubor]
stat -c %s soubor
zdroj | wc -c

3/4 Vygenerovat data

@data tvořená nulovými bajty#1
head -c velikost-P /dev/zero | zpracování
@data tvořená pseudonáhodnými bajty (maximálně 2 147 483 647 bajtů/bez omezení)#2
openssl rand počet-bajtů | zpracování
while openssl rand 1073741824; do :; done | head -c velikost-P | zpracování
@prázdná data#3
> soubor [> další-soubor]
: | zpracování
@data tvořená bajty konkrétní hodnoty#4 (4)
head -c velikost-P /dev/zero | tr \\0 $(printf '\\%03o' hodnota-bajtu ) | zpracování
@bajty 0 až 255#5
printf %02x {0..255} | xxd -r -p | zpracování
@příklad: vytvořit soubor o velikosti 2 MiB, tvořený bajty s hodnotu 37 (0x25)#6
head -c 2M /dev/zero | tr \\0 $(printf '\\%03o' 0x25) | zpracování

3/5 Vytvořit/prodloužit/zkrátit soubor na disku

@zkrátit či prodloužit soubor na uvedenou velikost (obecně/příklady...)#1 (5)
truncate -s nová-velikost-P soubor
truncate -s 0 soubory/k-vyprazdneni.dat
truncate -s 4M soubory/na-4-mebibajty.dat soubory/dalsi-na-4-mebibajty.dat
@vytvořit prázdný soubor (vyprázdnit, pokud existuje)(alternativy)#2
truncate -s 0 [--] soubor [další-soubor]
> soubor [> další-soubor]
@vytvořit soubor tvořený nulovými bajty (alternativy)#3
truncate -s 0 [--] soubor && truncate -s velikost-P [--] soubor
head -c velikost-P /dev/zero >soubor

3/6 Spojování a dělení souborů

@spojit soubory#1 (6)
cat soubor >cíl
@rozdělit soubor na díly po blocích určité velikosti (obecně/příklad)#2 (7)
split [--verbose] -b velikost-bloku-P [-typ-počítadla] [-apočet-znaků-počítadla] [--additional-suffix="přípona-za-počítadlo"] cesta/k/souboru předpona/cesty/výsledků
split --verbose -b 4M -d -a 5 --additional-suffix=".část" "původní soubor.jpg" ""
@rozdělit soubor na N přibližně stejně velkých dílů (obecně/příklad)#3
split [--verbose] -n počet-dílů [-typ-počítadla] [-apočet-znaků-počítadla] [--additional-suffix="přípona-za-počítadlo"] [-e] cesta/k/souboru předpona/cesty/výsledků
split --verbose -n 7 -d -a 3 --additional-suffix=".část" "původní soubor.jpg" "část-"

3/7 Srovnání souborů podle obsahu

@jsou dva soubory po bajtech shodné?#1
cmp [-s] soubor1 soubor2
@jsou po bajtech shodné zadané úseky?#2
cmp [-s] -n bajtů-k-porovnání-P soubor1 soubor2 začátek1-P začátek2-P
@který ze dvou souborů je větší?#3 (8)
test $(stat -c %s "soubor1") -gt $(stat -c %s "soubor2")

3/8 Hexadecimální editory

@grafické rozhraní (GUI)#1 (9)
ghex soubor
@textové rozhraní (TUI)#2
hexcurse [-r bajtů-na-řádku] soubor

3/9 Transformace souboru

@obrátit po bajtech celý soubor#1 (10)
perl -MEnglish -0777 -n -e 'print(scalar(reverse($ARG)))' <vstupní-soubor >výstupní-soubor
@obrátit každou dvojici/čtveřici/osmici bajtů#2
dd iflag=fullblock,skip_bytes,count_bytes status=none conv=swab [if=vstupní-soubor] [of=výstupní-soubor]
xxd -e -g 4 [soubor] | xxd -r > cíl
xxd -e -g 8 [soubor] | xxd -r > cíl

3/10 Kódování (base64, uuencode, xor)

@zakódovat do/dekódovat z base64#1
base64 -w 0 [soubor]
base64 -d [soubor] | zpracování
@zakódovat do/dekódovat z uuencode#2
uuencode /dev/stdout < soubor | sed -n 'x;3,$p'
sed $'1i\\\nbegin 644 /dev/stdout\n$a\\\nend' temp.dat | uudecode > cíl
@symetrické kódování operátorem „xor“#3

3/11 Záplatování

@vytvořit záplatu#1
rdiff -- signature původní-soubor - | rdiff [-s] -- delta - nový-soubor - | gzip -9 >cíl-záplata.gz
@aplikovat záplatu#2
zcat záplata.gz | rdiff [-s] -- patch původní-soubor - - >cíl-soubor

4. Zaklínadla: Zpracování po bajtech

4/1 Vyjmout úsek bajtů

@vzít prvních N bajtů/kibibajtů/mebibajtů/gibibajtů#1
head -c N soubor
head -c NK soubor
head -c NM soubor
head -c NG soubor
@vzít prvních N bajtů/kilobajtů/megabajtů/gigabajtů#2
head -c N soubor
head -c NkB soubor
head -c NMB soubor
head -c NGB soubor
@vynechat prvních N bajtů/kibibajtů/mebibajtů/gibibajtů#3
zdroj | dd iflag=fullblock,skip_bytes,count_bytes status=none skip=N | zpracování
zdroj | dd iflag=fullblock,skip_bytes,count_bytes status=none skip=NK | zpracování
zdroj | dd iflag=fullblock,skip_bytes,count_bytes status=none skip=NM | zpracování
zdroj | dd iflag=fullblock,skip_bytes,count_bytes status=none skip=NG | zpracování
@vynechat prvních N bajtů/kilobajtů/megabajtů/gigabajtů#4
zdroj | dd iflag=fullblock,skip_bytes,count_bytes status=none skip=N | zpracování
zdroj | dd iflag=fullblock,skip_bytes,count_bytes status=none skip=NkB | zpracování
zdroj | dd iflag=fullblock,skip_bytes,count_bytes status=none skip=NMB | zpracování
zdroj | dd iflag=fullblock,skip_bytes,count_bytes status=none skip=NGB | zpracování
@příklad: vzít třetí mebibajt souboru#5
dd iflag=fullblock,skip_bytes,count_bytes status=none skip=2M count=1M <soubor.dat
@příklad: vynechat třetí mebibajt souboru#6
(dd iflag=fullblock,skip_bytes,count_bytes status=none count=2M && dd iflag=fullblock,skip_bytes,count_bytes status=none count=1M of=/dev/null && cat) <soubor.dat

4/2 Analyzovat po bajtech

@určit počet bajtů určité hodnoty v daném souboru (obecně/určit počet bajtů 0xa9)#1
tr -cd \\$(printf %o hodnota-bajtu) <soubor | wc -c
tr -cd \\$(printf %o 0xa9) <soubor | wc -c

4/3 Konverze na/z číselné reprezentace

Poznámka: Následující zaklínadla generují/přijímají jednu číselnou hodnotu na každou řádku.

@bajty hexadecimálně „00“ až „FF“ (na čísla/z čísel)#1
zdroj | xxd -p -u -c 1 | zpracování
zdroj | xxd -r -p | zpracování
@bajty desítkově „0“ až „255“ (na čísla/z čísel)#2
zdroj | od -A n -t u1 -v -w1 | tr -d " " | zpracování
zdroj | sed $'1i\\\nobase=16' | bc | sed -E 's/^.$/0&/' | xxd -r -p | zpracování
@bajty binárně „00000000“ až „11111111“ (na čísla/z čísel)#3
zdroj | xxd -b -c 1 | cut -d " " -f 2 | zpracování
zdroj | sed $'1i\\\nobase=16\\\nibase=2' | bc | sed -E 's/^.$/0&/' | xxd -r -p | zpracování
@bajty osmičkově „000“ až „377“ (na čísla/z čísel)#4
zdroj | od -A n -t o1 -v -w1 | tr -d " " | zpracování
zdroj | sed $'1i\\\nobase=16\\\nibase=8' | bc | sed -E 's/^.$/0&/' | xxd -r -p | zpracování

4/4 Přepsat/nahradit/vynechat/vložit bajty

@nastavit bajt na určité adrese#1 (11)
printf '%08x:%02x\n' adresa hodnota-bajtu [další-adresa hodnota-bajtu] | xxd -r -c 1 - soubor
@přepsat úsek bajtů v souboru#2 (12)
zdroj | dd iflag=fullblock,skip_bytes,count_bytes [status=progress] conv=nocreat,notrunc [oflag=seek_bytes seek=kam-zapsat] of=soubor-k-zápisu
@vypustit bajty uvedených hodnot/všechny kromě bajtů uvedených hodnot#3
zdroj | tr $(printf -d '\\%03o' bajt) | zpracování
zdroj | tr $(printf -cd '\\%03o' bajt) | zpracování
@tabulkový překlad bajtů#4 (13)
zdroj | tr $(printf '\\%03o' původní-bajt) $(printf '\\%03o' náhradní-bajt) | zpracování
@příklad: nahradit v souboru a.bin bajty 0x0a hodnotou 0x0c a výsledek zapsat do b.bin#5
tr $(printf '\\%03o' 0x0a) $(printf '\\%03o' 0x0c) <a.bin >b.bin
@vynechat úsek mezi dvěma adresami#6
@nahradit úsek mezi dvěma adresami vstupem#7
@vložit nový úsek dat na zadanou adresu (obecně/příklad)#8
zdroj-nového-úseku | cat <(head -c adresa-desítkově [--] soubor) - <(tail -c +$((adresa-desítkově+1)) [--] soubor) | zpracování
cat novy-usek.dat | cat <(head -c 21734 puvodni.dat) - <(tail -c +$((21734+1)) puvodni.dat) >novy-soubor.dat

5. Parametry příkazů

Důležitý tip: v každém příkazu, kde je „| zpracování“, můžete místo něj uvést přesměrování do souboru.

5/1 split

split -typ-dělení -typ-počítadla [-další -parametry] vstupní-soubor předpona/výstupu

Typ dělení může být:

  • -b velikost-P :: dělení na bloky pevné velikosti
  • -C velikost-P :: dělení po záznamech; do každého dílu zapíše jen tolik záznamů, aby nepřekročil uvedenou velikost // [ ] vyzkoušet!
  • -l počet-záznamů :: dělení po záznamech; do každého dílu zapíše pevný počet záznamů (poslední díl jich může obsahovat méně) // [ ] vyzkoušet!
  • -n počet-výstupních-souborů :: pokusí se rozdělit vstup na daný počet přibližně stejně velkých souborů.

Při dělení po záznamech je možno uvést parametr -t, který specifikuje ukončovač záznamů; např.:

  • -t \\0 :: nulový bajt
  • -t $'\t' :: tabulátor
  • -t $'\n' :: konec řádky (výchozí hodnota)
  • -t $'\xa0' :: bajt o hodnotě 0xa0

Typ počítadla může být:

  • (neuvedený) :: použijí se malá písmena anglické abecedy (aa, ab, ac, ...)
  • -d :: použijí se desítkové číslice (00, 01, 02, ...)
  • -x :: použijí se šestnáctkové číslice (00, 01, ..., 09, 0a, 0b, 0c, 0d, 0e, 0f, 10, ...)
  • --numeric-suffixes=hodnota :: použijí se desítkové číslice počínaje uvedenou hodnotou (např. 12, 13, ...)

Další parametry mohou být:

  • -ačíslo :: počet „číslic“ počítadla (výchozí hodnota: 2)
  • --additional-suffix=řetězec :: řetězec k připojení za počítadlo (Poznámka: nesmí obsahovat „/“.) Výchozí hodnotou je prázdný řetězec.
  • --verbose :: oznámí vytvoření každého výstupního souboru

Tip: Místo vstupního souboru může být „-“; příkaz pak čte ze standardního vstupu.

5/2 xxd

xxd [parametry] vstupní-soubor
zdroj | xxd -r [parametry] - soubor-k-přepsání
zdroj | xxd -r [parametry] - | zpracování
-ppoužije „holý“ hexadecimální formát bez adres (výchozí chování: čitelný formát s adresami)
-uv hexadecimálních číslech použije velká písmena (výchozí chování: malá písmena)
-c bajtůpočet bajtů na řádek výstupu
-s adresazačne vypisovat od zadané adresy (např. „0x80“)
-l počet-bajtůvypíše nejvýše zadaný počet bajtů
zdroj | xxd -r [parametry] | zpracování
zdroj | xxd -r [parametry] - soubor-k-editaci
-c bajtůpočet bajtů na řádku vstupu (nemá smysl v kombinaci s parametrem „-p“)
-počekává „holý“ hexadecimální formát bez adres; bílé znaky jsou ignorovány
-seek posunpřed každým zápisem k adrese přičte uvedený posun (např „0x80“)

6. Instalace na Ubuntu

@rdiff, xxd, ghex, hexcurse#1
sudo apt-get install rdiff xxd ghex hexcurse
@crc32#2
sudo apt-get install libarchive-zip-perl
@uudecode, uuencode#3
sudo apt-get install sharutils

Ostatní použité příkazy jsou přítomny i v minimální instalaci Ubuntu.

7. Tipy a zkušenosti

  • Příkaz „cmp“ je nejrychleji čtoucí příkaz, který znám, lze jej použít např. pro výkonnostní test SSD disku.

8. Další zdroje informací

9. Zákulisí kapitoly

V této verzi kapitoly chybí:

  • nic

Tato kapitola záměrně nepokrývá:

  • nic
1 Analogicky můžete také použít příkazy „sha1sum“, „sha224sum“, „sha384sum“ a „sha512sum“. Existuje také obecný „shasum“.
2 Heše souborů a jejich názvy (včetně cesty) se uloží do uvedeného souboru.
3 Poznámka: Příkaz „crc32“ lze použít i s více soubory, ale v takovém případě vypisuje ke kontrolním součtům i názvy souborů bez odzvláštnění, což znamená, že nelze bezpečně zpracovat soubory jejichž cesta obsahuje znak konce řádky.
4 Hodnotu bajtu můžete zadat dekadicky (např. „127“), hexadecimálně (např. „0x7f“) nebo osmičkově (např. „0177“).
5 Prodlužuje se vždy nulovými bajty, zkracuje se zprava (tzn. od konce). Pokud soubor neexistuje, vytvoří se.
6 Tip: mezi soubory můžete vložit data ze standardního vstupu zadáním parametru minus („-“) místo jednoho souboru.
7 Pro „-typ-počítadla“ viz popis příkazu „split“ v sekci Parametry příkazů. Pro kontrolu vřele doporučuji použít parametr „--verbose“.
8 Pokud příkaz uspěje, „soubor1“ je větší; jinak je nutno soubory otestovat ještě v opačném pořadí; pokud obě testování selžou, jsou soubory stejně velké.
9 Když otevřete nové okno příkazem „View“/„Add View“, nové okno nebude mít sloupec s adresami, bez něhož je obtížně použitelné. Vyřešit se to dá tak, že zvolíte „Edit“/„Preferences“ a na kartě „Editing“ odškrtnete a zaškrtnete pole „Show offset columns“; pak se sloupec s adresami zobrazí ve všech oknech editoru.
10 Při obracení velkých souborů se ujistěte, že se do paměti RAM a odkládacího souboru vejde dvojnásobek celého souboru! To znamená, že např. pro obrácení souboru o velikosti 4 GiB potřebujete 8 GiB prostoru.
11 Adresy nemusejí být v pořadí, dokonce se mohou opakovat; xxd zapíše jeden bajt po druhém.
12 Hodnota „kam-zapsat“ je obyčejné desítkový index počátečního bajtu, počítáno od nuly. Zápis může pokračovat za stávající konec souboru, ale pokud bude cílová adresa ležet za koncem souboru, zápis začne bezprostředně za poslední existující bajt.
13 Počet „původních bajtů“ musí přesně odpovídat počtu náhradních bajtů, jinak výsledek nemusí odpovídat očekávání.
[BY-SA]

Veškerý obsah této stránky (text, obrázky, zdrojový kód) je možno upravovat a šířit pod podmínkami licence Creative Commons Attribution-ShareAlike 4.0 International. Upozorňuji, že uvedená licence vyžaduje uvedení seznamu autorů, licence a zdroje a poskytnutí stejné či kompatibilní licence k provedeným změnám, jsou-li nějaké. Příslušné údaje jsou dostupné na stránce „Přehled autorů“. Šíření obsahu bez těchto údajů nebo šíření upravené verze bez poskytnutí adekvátní licence k provedeným úpravám je pravděpodobně porušení licenčních podmínek a může být postihováno. Poskytování zdrojového kódu při šíření není touto licencí vyžadováno.

Pro nové verze, další informace, aktuální zdrojový kód a možnost se zapojit do projektu „Linux: Kniha kouzel“ navštivte jeho repozitář na GitHubu.