Hlavní navigace

Žůžo shell

25. 10. 2001
Doba čtení: 8 minut

Sdílet

Před časem jsem tu publikoval krátký seriál článků o interpretech příkazů a práci s příkazovým řádkem. Pochvaloval jsem si, jak dobré služby mi odvádí tcsh. V diskusi se několik čtenářů ozvalo, že znají ještě lepšího pomocníka - zsh. Je načase dát jim za pravdu.

Mám-li jedním slovem charakterizovat kvality zsh, je prostě žůžo (možná právě tohle znamená „z“ v jeho názvu). Tenhle interpret dovede se žolíkovými znaky či s doplňováním příkazového řádku neuvěřitelné věci. Posuďte sami.

Obecně o programu

Z-shell, čili zsh, vyvinul Paul Falstad s cílem vytvořit interpret s chováním podobným Korn shellu (ksh), ovšem náležitě vylepšeným. Postupem času převzala otěže skupina programátorů, kterou v současné době koordinuje Peter Stephenson.

zsh je živý projekt. Jeho poslední verze (4.0.2) vyšla v červnu letošního roku. V distribucích proto najdete zpravidla starší kousky - 3.0, případně 3.1, což byla betaverze pro 4.0. Vzhledem k tomu, že některé vlastnosti byly zásadně přepracovány (doplňování jmen je asi nejvýznamnější z nich), vřele doporučuji instalovat si novější verzi. Najdete ji například na jeho domácích stránkách zsh.sunsite.dk.

Také dokumentace je na velmi dobré úrovni. Vedle obvyklé sady manuálových stránek zahrnuje i obsáhlou uživatelskou příručku o rozsahu přes 250 stran (a to je napsáno jen pět kapitol ze sedmi).

Takže první dojem velmi dobrý, ale podívejme se, co dovede. Následující text nemá být příručkou začínajícího uživatele. Spíše se pokusím upozornit na věci, které se mi zdají být atraktivní a kvůli kterým jsem nedávno provedl  chsh -s /bin/zsh satrapa.

Soubory čili žolíci

V sortimentu žolíkových znaků najdete pochopitelně obvyklé věci, jako ?  (libovolný znak), *  (libovolný řetězec), [a-f]  (libovolné z písmen „a“ až „f“), [^a-f]  (cokoli kromě písmen „a“ až „f“) či (raz|dva)  (vyhoví „raz“ nebo „dva“). Méně obvyklá je možnost zadat číselné rozmezí ve tvaru <1-100>, kde jak horní, tak dolní hranici můžete vynechat.

Skutečné orgie se ale rozpoutají, až když zapnete volbu EXTENDED_GLOB (příkazem setopt EXTENDED_GLOB). Asi nejužitečnější je schopnost zalézat do podadresářů. Zapíšete-li jako jméno souboru **/ cosi, bude vyhledávat jména souborů vyhovující vzoru cosi v aktuálním adresáři i v celém stromě adresářů, který se nachází pod ním. Takže například ls **/*.html vypíše všechny soubory s příponou „.html“ ze stromu začínajícího aktuálním adresářem. Ve spojení s grepem, tarem a dalšími dostáváte do ruky ideálního pomocníka.

Dvojice hvězdiček nenásleduje symbolické odkazy na adresáře. Má-li to zsh dělat, použijte tři hvězdičky.

Ovšem soubory můžete také vylučovat. Pokud ke vzoru pro jméno souboru přidáte vlnku následovanou druhým vzorem, znamená to, že ze seznamu vyhovujících má vyškrtnout ta jména, která vyhovují vzoru. Třeba rm *.o~p* vymaže všechny soubory s příponou „.o“ kromě těch, jejichž jméno začíná písmenem „p“ (za vlnkou je „p*“).

Navíc můžete omezit vyhovující soubory určitými charakteristikami. Uvedete je v závorce za vzorem pro jméno souboru. Například ls a*(/) vypíše názvy všech adresářů, jejichž jméno začíná na „a“. Požadovat lze ledacos:

Tabulka č. 205
. běžný soubor
/ adresář
@ symbolický odkaz
* spustitelný soubor (nikoli adresář)
r, w či x odpovídající právo pro vlastníka
R, W či X odpovídající právo pro všechny
f práva má dotyčná práva
U moje soubory
G soubory mé skupiny
u uživatel soubory daného uživatele (číslo nebo :jméno:)
g skupina soubory dané skupiny (číslo nebo :jméno:)
m doba, a doba doba poslední změny/přístupu
L velikost podle velikosti souboru - např. (Lm+1) znamená soubory větší než 1 MB

A to jsem ještě něco vynechal. Stručně řečeno mechanismus pro rozvoj žolíkových znaků v podstatě obsahuje find a umožňuje dělat brutální věci. Kritéria lze kombinovat a také negovat (znakem ^, neguje vše za sebou). Příklad: ls **/*(Ux^/) vypíše ze stromu začínajícího aktuálním adresářem všechny soubory, které patří mně, mám právo je provádět a nejsou to adresáře.

Ovšem tím se sortiment schopností žolíkových znaků pořád ještě nevyčerpal. Můžete si předepsat pořadí, ve kterém se vyhovující jména vloží do příkazového řádku. Můžete z nich nechat zkonstruovat něco složitějšího (nevkládat jen samotná jména, ale obalit je dalším textem). Můžete si jméno zapamatovat a později použít. Můžete zkrátka spoustu věcí.

Za speciální zmínku myslím stojí ještě možnost neurčitého srovnávání. Když před žolíkovým výrazem uvedete (#a počet), znamená to, že jméno souboru může obsahovat uvedený počet chyb (vynechané písmeno, přidané písmeno, přehozená písmena). Třeba ls (#a1)README vypíše REAME, READ.ME, FEADME i READEM, pokud jsou v aktuálním adresáři.

zsh, stejně jako v ostatních interpretech, žolíkovým znakům nevyhoví soubory, jejichž jména začínají hvězdičkou (pokud ji explicitně neuvedete). Zapnete-li však volbu GLOBDOTS, toto chování se změní a s tečkovaným jménem (s výjimkou „.“ a „..“) se zachází jako s každým jiným. Zkuste si ve svém domácím adresáři

setopt GLOBDOTS
ls *
ls

Editor příkazového řádku

Pro editaci příkazového řádku poskytuje zsh standardní současné pohodlí - kurzorové klávesy, historie a editace příkazů a podobně. Užitečné hledání v předchozích příkazech se aktivujete stiskem Ctrl-R, po němž napište hledaný řetězec. Opakovaným stiskem Ctrl-R poskočíte na další výskyt.

V souvislosti s historií je zajímavá volba HISTIGNORESPACE, která zařídí, že pokud příkaz zahájíte mezerou, neuloží se do historie. Přesněji řečeno se na chviličku uloží, ale následující příkaz jej přemaže. Lze také zakázat opakované ukládání příkazů, které již v historii jsou (volba HISTIGNOREALLDUPS). Zopakujete-li příkaz, jeho starší exemplář se z historie vymaže.

zsh dovede opravovat překlepy na příkazovém řádku (což je jedna z věcí, které u bash dost chybí). Po nastavení setopt CORRECT si všímá jen příkazů, po setopt CORRECTALL opravuje celý řádek. Pokud ji chcete pro některý ze zadávaných příkazů vyřadit, můžete mu předsadit nocorrect. Například v ukázkovém souboru .zshrc je zaveden alias pro příkazy mv a cp, který je převádí na nocorrect mv a nocorrect cp, aby se při přejmenovávání či kopírování na podobné jméno (např. .htm na .html) pokaždé nevyptával, jestli jste se náhodou nepřeklepli.

V čem je ovšem zsh zcela brutální, je doplňování slov na příkazovém řádku. Všichni jsme zvyklí, že když začneme psát jméno příkazu či souboru a stiskneme tabulátor, interpret doplní zbytek (pokud je jednoznačný), vypíše možnosti nebo udělá něco podobného. V případě zsh se v takovém případě začnou dít VĚCI.

V souvislosti s doplňováním mám pro vás dvě zprávy: dobrou a špatnou. Ta špatná je, že si je nejspíš nedokážete nakonfigurovat. Ne, že by to nešlo, ale nejspíš se vám nebude chtít louskat těch sedmdesát stránek, na kterých je to popsáno v uživatelské příručce. Dobrá zpráva je, že to nejspíš nebudete potřebovat, protože standardní konfigurace je monumentální. Například po acroread (což není zrovna standardní příkaz) doplňuje jen PDF soubory.

Příkladem opravdu drsného doplňování je, když napíšete tar xzvf soubor.tar.gz a a stisknete tabulátor. Interpret si rozbalí archiv a doplňuje jména souborů v něm obsažených začínající od „a“.

Dlužno přiznat, že tato konfigurace doplňování není implicitní (zřejmě by příliš zdržovala na nevýkonných strojích). Chcete-li ji aktivovat, musíte (například v .zshrc) provést

autoload -U compinit
compinit

Nabízené soubory umí i obarvit. Pokud si barvíte výstup z ls, možná by se vám líbilo, aby soubory nabízené tabulátorem měly stejné barvy. Zařídí to následující dvojice příkazů:

zmodload -i zsh/complist
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}

Příjemné je, že tabulátor v zsh umí rozbalit i žolíkové znaky. Napíšete-li třeba ls *.c a stisknete tabulátor, interpret nahradí „*.c“ seznamem souborů, které mu vyhovují. Občas může být rychlejší nechat si takto rozbalit seznam a vymazat z něj nežádoucí prvky, než konstruovat zběsilý žolíkový výraz, který je vyloučí.

Aliasy

Chování aliasů pro mne bylo překvapením, ale pak jsem zjistil, že odpovídá konvencím v bash a ksh. Zapisují se ve tvaru

alias jméno= význam

a nemohou mít v sobě parametry. Alias prostě nahradí první slovo na řádku daným významem a případné parametry přidá za něj. Chcete-li vkládat parametry dovnitř, můžete si vytvořit uživatelskou funkci. Takže například můj oblíbený alias psg, který ve výpisu běžících procesů vyhledává zadaný řetězec, by byl realizován touto definicí

psg () { ps -ax | grep $* | grep -v grep }

Musím přiznat, že se mi to líbí více, než dosavadní C-shellovské

alias psg 'ps -ax | grep \!* | grep -v grep'

Unikátem jsou takzvané globální aliasy, které vyrobíte volbou -g. Takový alias se nahrazuje kdekoli na řádku, nejen na jeho začátku. Například po zavedení

alias -g L="| less"

můžete psát ls -l L a zsh si příkaz přetvoří na ls -l | less. Hezké, ale trochu nebezpečné. Podle zákona schválnosti se takový alias rozbalí v tu nejnevhodnější chvíli.

Různé drobnosti

Prompt čili výzva interpretu příkazů může významně přispět k vaší orientaci. Obvyklým problémem je, jak dostat do výzvy co nejvíce užitečných informací a zároveň si ponechat dostatek prostoru na vlastní příkaz.

Častým řešením je víceřádková výzva. V zsh na to ale můžete jít i jinak. Výzvu si můžete rozdělit na levou ( $PROMPT nebo $PS1) a pravou část ( $RPS1). Pokud je příkaz dlouhý, pravá část prostě zmizí, jakmile do ní při psaní příkazu dorazíte. Zkuste třeba

PS1='%B>%b'
RPS1='%B<%h %m:%~%b'

Možná se vám to bude líbit.

Šikovná je také funkce zmv, která umožňuje skupinové přesouvání/přej­menovávání. Jedná se o externí funkci, která implicitně není k dispozici. Nejsnadněji si ji zpřístupníte, pokud třeba do .zshrc přidáte autoload zmv.

Funkce zmv používá mechanismu zapamatování - podobně jako třeba regulární výrazy. V prvním parametru vyznačíte pomocí závorek některé části a ve druhém se na ně pak můžete odvolávat. Jako obvykle se zapamatované řetězce určují pozičně - obsah prvních závorek je přístupný prostřednictvím $1, obsah druhých je $2 a tak dále. Například

zmv (*).doc $1.txt

změní všem souborům s příponou .doc příponu na .txt (jméno souboru se zapamatuje a použije při nahrazení). Nebo přejmenování souborů README na CTIMNE v celém stromě začínajícím v aktuálním adresáři zajistí

zmv (**/)README $1CTIMNE

Také pro příkaz cd se nabízí pár vylepšení. Například si můžete nastavit volbu AUTOCD a pak můžete na cd zcela zapomenout. Když napíšete na příkazový řádek samotné jméno adresáře, zsh si příkaz cd doplní sám. Zajímavé je také

cd starý nový

které v aktuální cestě nahradí všechny výskyty řetězce starý řetězcem nový. Ideální, pokud se chcete přesunout do téhož adresáře, ovšem v jiné verzi programu (například když se vrtáte v jádře Linuxu a chcete se podívat, jak je to ve starší verzi).

Možná vás potěší, že zsh má vestavěného FTP klienta nebo že pro přizpůsobení jeho chování můžete použít styly. Určitě bude mít i nějaké milé vychytávky v oblasti programování, ale já v interpretu v podstatě neprogramuji, takže jsem v této oblasti hluboce nekompetentní.

CS24_early

Ovšem pro interaktivní práci určitě stojí za pohled.

Příloha: .zshrc, jak jsem si jej v potu tváře upravil.

Byl pro vás článek přínosný?

Autor článku

Pavel Satrapa působí na Ústavu nových technologií a aplikované informatiky na Technické univerzitě v Liberci, píše knihy a motá se kolem tuzemské akademické sítě CESNET.