V Linuxu je text král a nejsilnější trik celého systému je zdánlivě banální: výstup jednoho programu pošleš jako vstup druhého. Místo jednoho obřího nástroje, který umí všechno, máš hromadu maličkých, z nichž každý dělá jednu věc dobře a ty je skládáš dohromady jako díly na pásové lince. Tomuhle skládání se říká roura (
|) a je to srdce takzvané unixové filozofie. Až ti to „cvakne", přestaneš hledat speciální program na každý problém a začneš si nástroje řetězit.
Pár pojmů na úvod
- stdin (standardní vstup, kanál 0) = odkud program čte data. Klávesnice, soubor, nebo výstup předchozího příkazu v rouře.
- stdout (standardní výstup, kanál 1) = kam program píše svůj normální výsledek. Ve výchozím stavu terminál, ale dá se přesměrovat do souboru nebo do dalšího příkazu.
- stderr (chybový výstup, kanál 2) = kam program píše chyby a hlášky. Je zvlášť od stdout, aby ti chyby nezaneřádily užitečný výstup, když ho posíláš dál rourou.
- Přesměrování = přesměruješ proud jinam než na terminál, do souboru (
>,>>), ze souboru (<), nebo chyby stranou (2>). - Roura (pipe,
|) = spojka, která bere stdout levého příkazu a strká ho na stdin pravého. - Filtr = program, který čte ze stdin, něco s tím udělá a píše na stdout. Přesně ty se řetězí
do rour,
grep,sort,uniq,wc,cut,tr,sed,awk.
Tři proudy: vstup, výstup a chyby zvlášť
Každý program má od startu tři „trubky" napojené do světa. Představ si je jako tři barevné hadice:
- 0, stdin: čtení dovnitř (co program dostává).
- 1, stdout: normální výstup ven (co program „říká").
- 2, stderr: chyby ven (co program „nadává").
Proč jsou výstup a chyby oddělené? Protože chceš umět poslat dál jen užitečná data, ale chybové
hlášky vidět na obrazovce. Kdyby byly smíchané, ls | grep neco by ti do výsledku občas propašovalo
i hlášku „soubor neexistuje" a rozbilo další zpracování.
# stdout jde do souboru, ale chyba se stejně vypíše na terminál
ls /existuje /neexistuje > vypis.txt
# → do vypis.txt se uloží nalezené, hláška o chybějícím souboru zůstane na obrazovce (stderr)
Přesměrování, kam tečou data
Přesměrování řekne shellu: „neposílej tenhle proud na terminál, ale sem".
echo "ahoj" > soubor.txt # stdout DO souboru. PŘEPÍŠE celý obsah!
echo "další" >> soubor.txt # stdout DO souboru. PŘIDÁ na konec (nepřepíše)
wc -l < soubor.txt # stdin ZE souboru (soubor krmí příkaz)
příkaz 2> chyby.log # stderr do souboru (chyby stranou)
příkaz &> vse.log # stdout I stderr do jednoho souboru
příkaz > vystup.log 2>&1 # totéž klasicky: "2 pošli tam, kam jde 1"
příkaz 2> /dev/null # chyby zahoď úplně (/dev/null = černá díra)
⚠️
>je nemilosrdné. Neptá se, nezálohuje, okamžitě vymaže obsah cílového souboru a napíše nový.>>naopak jen přidává. Nauč se ten rozdíl dřív, než si>omylem přepíšeš důležitý soubor.
Zápis 2>&1 čti jako „nasměruj kanál 2 tam, kam už míří kanál 1". Proto záleží na pořadí:
> soubor 2>&1 funguje (nejdřív 1 → soubor, pak 2 → za 1), kdežto 2>&1 > soubor pošle chyby ještě
na terminál, protože v tu chvíli 1 ještě míří na obrazovku.
Roura |, pásová linka z malých nástrojů
Roura je ta nejdůležitější věc v celé kapitole. Vezme stdout levého příkazu a napojí ho přímo na stdin pravého, bez ukládání do souboru, rovnou z paměti do paměti.
cat pristup.log | grep "ERROR" # vezmi log a nech jen řádky s ERROR
Tady je celá unixová filozofie: cat umí jen vypsat soubor, grep umí jen filtrovat řádky. Ani
jeden neumí to druhé, a to je záměr. Malé nástroje, každý dělá jednu věc dobře, a rourou z nich
poskládáš přesně to, co potřebuješ. Je to jako pásová linka: každý stroj udělá jeden úkon a pošle
polotovar dál.
Data tečou zleva doprava, každý díl je filtr, čte ze stdin, něco udělá, píše na stdout. Roura mezi nimi je ta trubka, co je propojuje.
Filtry, které použiješ pořád
Tohle je tvoje základní bedna nářadí. Každý z nich je filtr, dá se řetězit s ostatními.
grep, najdi řádky, které odpovídají vzoru.
grep "chyba" log.txt # řádky obsahující "chyba"
grep -i "chyba" log.txt # -i = ignoruj velikost písmen (Chyba, CHYBA…)
grep -n "chyba" log.txt # -n = přidej čísla řádků
grep -v "chyba" log.txt # -v = obrácení: řádky, které vzor NEobsahují
grep -r "TODO" . # -r = rekurzivně projdi celý strom adresářů
sort, seřaď řádky. uniq, zahoď opakující se sousední řádky.
sort jmena.txt # abecedně
sort -n cisla.txt # -n = číselně (jinak "10" < "2"!)
sort -rn cisla.txt # -r = obráceně (od největšího)
sort jmena.txt | uniq # unikátní řádky (uniq VYŽADUJE seřazený vstup!)
sort jmena.txt | uniq -c # -c = spočítej výskyty každého řádku
wc, počítání. cut, vyřízni sloupce. tr, nahraď/smaž znaky.
wc -l soubor.txt # -l = počet řádků (nejčastější použití)
cut -d':' -f1 /etc/passwd # -d = oddělovač, -f1 = první sloupec (uživatelská jména)
echo "Ahoj Svete" | tr 'a-z' 'A-Z' # převod na velká písmena → AHOJ SVETE
echo "a,b,c" | tr ',' '\n' # nahraď čárky novými řádky
sed a awk, ochutnávka dvou mocností
Až vyrosteš z grep/cut, čekají tě dva „těžkokalibrové" filtry. Teď jen ať víš, že existují.
sed, stream editor, hlavně na hledání a nahrazování textu:
sed 's/staré/nové/g' soubor.txt # nahraď "staré" za "nové": g = na každém výskytu v řádku
cat log.txt | sed 's/ERROR/CHYBA/g' # v proudu přejmenuj ERROR na CHYBA
Čti s/co/čím/g jako substitute (nahraď), co za čím, g = globálně (všechny výskyty na
řádku, ne jen první).
awk, nástroj na sloupce a tabulky. Umí toho hodně, ale nejčastěji ho uvidíš takhle:
awk '{print $1}' soubor.txt # vytiskni první sloupec každého řádku
awk '{print $1, $3}' soubor.txt # první a třetí sloupec
ps aux | awk '{print $2, $11}' # z výpisu procesů jen PID a název příkazu
$1, $2… jsou sloupce (rozdělené mezerami), $0 je celý řádek. Zatím ber sed a awk jako pozvánku,
až tě „malé filtry" přestanou stačit, vrátíš se k nim.
Praktická komba, co uvidíš každý den
Síla roury je v kombinaci. Pár klasik, které stojí za to umět nazpaměť:
# Kolik chyb je v logu?
cat aplikace.log | grep "ERROR" | wc -l
# Žebříček nejčastějších hodnot (top-fráze zdola nahoru)
cat pristup.log | cut -d' ' -f1 | sort | uniq -c | sort -rn
# Které IP adresy nás bušily nejvíc? (prvních 10)
cat pristup.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
To druhé kombo je klasika, kterou si zapamatuj: sort | uniq -c | sort -rn =
„spočítej výskyty a seřaď od nejčastějšího". Nejdřív sort (aby uniq viděl stejné řádky vedle sebe),
pak uniq -c (spočítá), pak sort -rn (seřadí číselně odshora). Přesně tak se dělá žebříček
četností, na cokoli od IP adres po slova v textu.
Failure modes, časté omyly začátečníků
>ti přepíše soubor bez varování.echo "x" > dulezity.txtvymaže starý obsah. Chceš-li přidat, je to>>. Když si nejsi jistý, nejdřív>>, přepsat můžeš vždycky.cmd < soubor > tentýž.soubor= katastrofa. Shell nejdřív vyprázdní cílový soubor kvůli>, teprve pak spustí příkaz, takže čteš z prázdna a přijdeš o data. Zapisuj do jiného souboru, pak přejmenuj.uniqbezsortnapřed.uniqzahazuje jen sousední duplicity. Bez předchozíhosortti nechá rozházené kopie a budeš se divit, proč tam pořád jsou. Pravidlo:uniqskoro vždy až posort.- Zapomenuté uvozovky u vzoru s mezerou.
grep chyba disku log.txtshell rozdělí,grephledáchybav souborechdiskualog.txt. Chcešgrep "chyba disku" log.txt. Vzor s mezerou vždy do uvozovek. - Chyby smíchané s daty. Když
příkaz | dalsinefunguje divně, může za to stderr. Přesměruj chyby (2> /dev/nullnebo2> chyby.log), ať vidíš jen čistý datový proud.
🛠️ Cvičení
- Přepiš vs. přidej. Vytvoř soubor přes
echo "první řádek" > pokus.txt, pak zkus jednou>a jednou>>s druhým textem a podívej se přescat pokus.txt, co se stalo. Vysvětli rozdíl vlastními slovy a řekni, kdy je>nebezpečné. - Postav rouru na počítání. Máš textový soubor s řádky. Napiš rouru, která spočítá, kolik řádků
obsahuje slovo
errorbez ohledu na velikost písmen. (Nápověda:grep -i,wc -l.) - Žebříček četností. Ze souboru, kde je na každém řádku jedno slovo (nebo z prvního sloupce logu),
vyrob top 5 nejčastějších hodnot i s počty. Poskládej
sort,uniq -c,sort -rn,head. - Sloupce a chyby stranou. Ze souboru
/etc/passwd(sloupce oddělené:) vytáhni jen uživatelská jména (první sloupec) a seřaď je abecedně. Zkus přitom nějaký příkaz, který částečně selže, a jeho chyby pošli do/dev/null. - stderr vs stdout. Spusť
ls existujici_slozka neexistujici_slozkaa rozděl výstup tak, aby normální výpis šel doout.txta chyby doerr.txt. Ověřcat, že v každém souboru je to správné.
Náčrt řešení: rozbal, až si cvičení zkusíš sám
- Přepiš vs. přidej,
echo "druhý" > pokus.txtsmaže „první řádek" a nechá tam jen „druhý".echo "druhý" >> pokus.txtnechá oba řádky.>je nebezpečné, protože maže okamžitě a bez ptaní, stačí omyl a přijdeš o obsah. Pozor:>vyprázdní soubor ještě před během příkazu, takžecmd < f > fzničíf. - Počítání řádků,
grep -i "error" soubor.txt | wc -l.grep -inajdeerror/Error/ERROR,wc -lspočítá řádky, které prošly. Pozor:wc -lpočítá řádky, ne výskyty, dvaerrorna jednom řádku se počítají jako jeden. Na výskyty by byl potřebagrep -onapřed. - Žebříček četností,
sort slova.txt | uniq -c | sort -rn | head -5. Nejdřívsort(aby stejná slova byla u sebe),uniq -cje spočítá,sort -rnseřadí číselně odshora,head -5vezme prvních pět. Pozor:uniqmusí jít až posort, jinak spočítá jen sousední duplicity a výsledek bude nesmysl. - Sloupce,
cut -d':' -f1 /etc/passwd | sort.-d':'říká, že oddělovač je dvojtečka,-f1bere první pole (jméno),sortseřadí. Chyby jiného příkazu utišíš přidáním2> /dev/null. Pozor:cutpočítá pole podle jednoho znaku oddělovače, víc mezer za sebou by dělalo prázdná pole (na to je lepšíawk). - stderr vs stdout,
ls existujici_slozka neexistujici_slozka > out.txt 2> err.txt.> out.txtchytí normální výpis (kanál 1),2> err.txtchytí chybu o chybějící složce (kanál 2). Pozor: pořadí2>&1je záludné,2>&1 > out.txtby chyby poslalo ještě na terminál, protože 1 v tu chvíli míří na obrazovku.
🧠 Otázky & odpovědi
K čemu je roura | a jak funguje?
Roura vezme stdout (normální výstup) levého příkazu a napojí ho přímo na stdin (vstup) pravého
příkazu, data tečou z paměti do paměti, bez ukládání do souboru. Díky tomu řetězíš malé nástroje
do delších pipeline: cat log | grep ERROR | wc -l = vypiš log, nech jen chybové řádky, spočítej je.
Je to jádro unixové filozofie „malé nástroje, každý dělá jednu věc dobře", místo jednoho obřího
programu skládáš mnoho jednoúčelových jako díly na pásové lince.
Jaký je rozdíl mezi > a >>?
> přesměruje výstup do souboru a přitom ho přepíše, starý obsah okamžitě a bez varování zmizí.
>> výstup do souboru jen přidá na konec, původní obsah nechá být. Praktický důsledek: echo x > f
smaže f a nechá tam jen „x"; echo x >> f nechá, co bylo, a přidá řádek. Nejčastější začátečnická
katastrofa je omylem přepsat důležitý soubor přes >. Ještě zákeřnější je cmd < f > f, shell nejdřív
vyprázdní f a teprve pak čte, takže přijdeš o data.
Proč jsou stdout a stderr oddělené proudy?
Aby se ti chybové hlášky nemíchaly s užitečnými daty. Normální výstup jde na kanál 1 (stdout),
chyby na kanál 2 (stderr). Když posíláš výstup dál rourou (cmd | dalsi), teče tam jen stdout,
chyby zůstanou viditelné na terminálu a nerozbijí ti další zpracování. Můžeš s nimi nakládat zvlášť:
2> chyby.log chyby uložit, 2> /dev/null úplně zahodit, 2>&1 je spojit s výstupem. Kdyby byly
v jednom proudu, každá hláška „soubor nenalezen" by ti zaneřádila data.
Proč se uniq skoro vždy dává až po sort?
Protože uniq zahazuje jen sousední stejné řádky, nehledá duplicity po celém souboru, jen porovnává
každý řádek s tím předchozím. Když jsou stejné hodnoty rozházené po souboru, uniq je nechá být.
sort je proto srovná vedle sebe a teprve pak uniq funguje správně. Odtud pochází klasické kombo
sort | uniq -c | sort -rn na žebříček četností: seřaď, spočítej výskyty (-c), a znovu seřaď
číselně odshora podle počtu.
K čemu jsou grep, cut, sort, wc a kdy který?
Jsou to základní filtry, čtou ze stdin, něco udělají, píšou na stdout. grep hledá řádky podle
vzoru (-i ignoruj velikost, -v obrať, -r rekurzivně, -n čísla řádků). cut vyřízne sloupce
(-d oddělovač, -f číslo pole), na text s pevnými sloupci jako /etc/passwd. sort seřadí (-n
číselně, -r obráceně). wc -l spočítá řádky. Poskládané rourou pokryjí většinu každodenní práce
s textem; na složitější úpravy pak přijdou sed (nahrazování) a awk (sloupce a tabulky).
