Spouštění prorgramů je základní činnost každého shellu. Protože všechny zde zmiňované operační systémy vycházejí ze stejných kořenů, fungují základní operace shellu dodnes všude stejným způsobem.
Každý program může při svém startu od shellu obdržet parametry, které budou ovlivňovat jeho činnost. Tyto parametry zadává uživatel tak, že je napíše za jméno spouštěného programu jako slova oddělená mezerami. Na programu samotném (resp. jeho autorovi) pak je, aby tomuto seznamu parametrů porozuměl a zařídil se podle nich.
Zkuste si ve svém unixovém terminálu spustit příkaz ls
a pak příkaz ls -l -R --reverse
. Pokud jste ve Windows, zkuste spustit například dir
a pak příkaz dir /O /W
. Jak jistě vidíte, parametry změnily chování obou příkazů. Tyto příkazy jsou totiž naprogramovány tak, aby těmto specifickým parametrům rozuměly. Pokud zadáte parametr, který program nezná, programy zřejmě vypíší chybové hlášení.
Jak ale zjistíme, jakým parametrům program rozumí? Dělá se to jednoduše tak, že v každém programu je naprogramována nápověda. Rozumný program rozumí parametru -h
nebo --help
(konvence v unixových systémech) nebo /?
(konvence v MS DOSu a Windows). Uživatelé shellu to obvykle vědí a před spuštěním neznámého programu se na tuto nápovědu podívají. Nejsou pak překvapení, když spustí program a ten na ně jen bliká textovým kurzorem...
Parametry nejsou žádné tajemné kouzelné formule. Jsou to obyčejné textové řetězce, které shell uloží do paměti programu, kde k nim má program přístup (jde o pole textových řetězců). Programátor pak tyto parametry může přečíst a zpracovat.
To, že některé parametry začínají pomlčkou, jiné dvěma pomlčkami a ve Windows lomítkem, jsou pouze konvence. Díky nim můžeme v programu snadněji rozlišovat mezi přepínacími a jinými parametry jako jsou třeba číselné vstupy nebo jména souborů. Vše se předává jako text, takže když takto předáváme do programu číselné hodnoty, je potřeba je v programu nejprve vyčíslit (převést textový řetězec na číselnou hodnotu).
Očekává-li program data na standardním vstupu, program se po spuštění zastaví, bliká kurzorem a čeká, až něco napíšete klávesnicí. Poté, co něco napíšete a stisknete klávesu Enter, se aktuální řádek pošle programu ke zpracování. To čekání na Enter dělá bufferování vstupu. O toto se programátor v jazyce C nestará, to má na starosti systém (knihovna). Můžete také rovnou skenovat kódy stisknutých kláves, což ale naštěstí není v jazyce C triviální problém, takže se k tomu začátečníci jen tak nedostanou.
Když program něco tiskne na standardní výstup, objeví se to za normálních podmínek na obrazovce (v okně terminálu). Problém nastává, když program takto realizuje standardní vstup a výstup a vy se rozhodnete zadávat vstup skutečně z klávesnice. Pak snadno dojde k tomu, že se vstup i výstup míchají spolu na jedné obrazovce (v jednom okně) a vy snadno ztratíte přehled, co je co. Začínající programátoři pak mají tendenci řešit různě formátování takového míchaného vstupu a výstupu a diví se, že to nefunguje, jak by chtěli.
Moje rada: nezadávejte vstup do takových programů ručně z klávesnice. Připravte si data do souboru, kde si je naformátujete, jak chcete (nebo jak to vyžaduje program) a pak je na vstup programu přesměrujte. Teď už to umíte.
Žádný CLI program s trochou sebeúcty si nepovídá s uživatelem. Představte si výše zmiňované programy ls
a dir
, kdyby místo užitečné práce s vámi klábosily (Ahoj uživateli. Kolik chceš vypsat souborů ze složky? Můžu už skončit?). Tento způsob interakce s uživatelem se hodí jen pro velmi specifické účely (např. Turingův test), ale většinou to uživatele jen otravuje a zdržuje. Také to brání použití programu ve skriptech.
Jak ale jinak dostat do programu data, aniž bychom museli v programu otevírat a zpracovávat soubory? Dáme data do souboru a pošleme jej do programu. Ano, není to chyba. Každý program, který čte data ze standardního vstupu (např. z klávesnice) umí tato data číst i ze souboru. Stačí k tomu použít shell a jeho schopnost přesměrování souboru na vstup programu, přesměrování výstupu programu do souboru a propojení výstupu a vstupu dvou programů pomocí roury.
Řekněme, že máte textový soubor text.txt, kde je na každém řádku jedno slovo (pokud jej nemáte, vytvořte si jej a zkopírujte do něj třeba obsah tohoto odstavce). Pro demonstraci přesměrování použijeme příkaz sort
, který najdete v Linuxu i ve Windows. Pokud jej spustíme bez parametrů, čte řádky ze standardního vstupu (klávesnice) a řadí přečtené řádky podle abecedy. My mu ale klávesnici nahradíme skutečným souborem. Nechme zatím stranou, že příkaz sort
umí zpracovat soubor i bez přesměrování, když mu jeho jméno dáme jako parametr příkazového řádku.
Nyní můžeme přesměrovat soubor text.txt na vstup programu pomocí operátoru shellu <. Výstup programu se do nového souboru přesměruje operátorem >. Můžete si to zkusit sami podle ukázky 2. Všimněte si, co se kdy tiskne na obrazovku.
Pozor! Operátory < a > nejsou parametry programu. Jde o záležitost shellu, který je odchytí a zařídí vše potřebné.
Co když chceme výsledek jednoho programu rovnou zpracovat jiným programem? Není potřeba vytvářet pomocný soubor, do něhož bychom přesměrovali výstup jednoho programu a pak jej posílali na vstup druhého programu. Jde to udělat elegantněji rourou.
Ukážeme si to na jednoduchém příkladu sort < text.txt | more
. Výstup programu sort
se tady posílá rourou (|, svislítko) do programu more
. Program more
čte text ze vstupu a tiskne jej na výstup tak, že pokud je text delší než by se vešlo do okna terminálu, zobrazí jej stránkovaně, tj. po vypsání jedné stránky čeká na stisk klávesy, aby zobrazil další stránku.
Přesměrování souborů i roury fungují stejně v unixových systémech i ve Windows. Bude to fungovat i s vaším programem, pokud umí zpracovávat standardní vstup (z klávesnice) a tisknout výsledky na standardní výstup (na obrazovku). Takto mohou fungovat programy napsané téměř v libovolném jazyce, nejen v C.
Zkuste si to. Na obrázku 4 v předchozí kapitole jsem takto spustil svůj program otoc, který tiskne řádky získané ze vstupu s opačným pořadím znaků.
Chování shellu lze ovlivnit proměnnými prostředí. Proměnná PATH slouží k vyjmenování složek v nichž jsou programy, které lze spouštět jménem bez uvedení cesty. Ve Windows sem takto například můžete přidat složku s nainstalovaným překladačem jazyka C, abyste nemuseli při ručním spouštění programátorských nástrojů používat dlouhé příkazy s cestou (například když si nainstalujete Code::Block i s překladačem a chcete si ručně hrát s jednotlivými nástroji přímo z příkazového řádku).
V Linuxu se proměnná PATH tradičně nastavuje v domovské složce uživatele v souboru .bashrc tak, že do něj přidáte řádek PATH=$PATH:~/bin
. Složky jsou v proměnné odděleny dvojtečkou, $PATH
je původní hodnota proměnné a ~/bin
je nová složka, kterou přidávám do proměnné PATH. Jde o složku bin v mé domovské složce (domovská složka má v Linuxu zkratku ~).
Chcete-li zjistit, jakou skutečně hodnotu tato proměnná obsahuje, napište v shellu příkaz echo $PATH
.
Ve Windows se proměnná PATH nastavuje pomocí dialogového okna (ve starém DOSu byla nastavována v dávkovém souboru AUTOEXEC.BAT). V různých verzích se to naneštěstí nastavuje trochu jinde. Samotné okno, kde se to nastavuje, se jmenuje Proměnné prostředí (Environment variables), které je dostupné v rozšířených vlastnostech systému v Control Panelu. Oproti Linuxu se zde jednotlivé cesty neoddělují dvojtečkou (protože dvojtečka se používá za názvem disku), ale středníkem.
V okně příkazového řádku Windows se obsah proměnné PATH zjistí spuštěním příkazu path
.