Zsh
Współczesna powłoka systemowa to dużo więcej niż okienko do wpisywania literek. Niektórzy z nas spędzają w niej wiele czasu i chcieliby wykonywać swoje działania możliwie najbardziej efektywnie. Zsh, to kolejna powłoka obok csh, tcsh, ksh, sh czy wreszcie domyślnego w większości dystrybucji Linuksa basha. Ceniony przez zaawansowanych użytkowników, pozwala wykonywać interaktywne zadania wygodniej niż alternatywy. Stopień pokrewieństwa zsh z innymi powłokami jest znaczny – w zasadzie ten shell dziedziczy najlepsze cechy konkurentów i dodaje własne. Nie będzie dużej przesady w stwierdzeniu, że zsh można używać jak basha i nawet wtedy będzie widać poprawę. Choć zsh pozwala pisać skrypty, a nawet oferuje w tym zakresie więcej niż bash, w praktyce lepiej pisać skrypty w bashu lub sh z uwagi na przenośność – zsh jest mistrzem pracy interaktywnej, powłoką z wyboru dla każdego kto spędza dużo czasu w terminalu.
Wbrew pozorom zsh nie jest żadną nowością – ma już ponad 20 lat. Ma świetną dokumentację (patrz ramka obok) i można znaleźć na jego temat w Internecie wiele artykułów i postów na blogach, ale w odróżnieniu do basha trudno do zsh znaleźć coś w księgarni, nawet w literaturze anglojęzycznej – jest w zasadzie tylko jedna książka: From Bash to Z Shell: Conquering the Command Line.
Konfiguracja
Niespodzianek nie ma:
- ~/.zshenv
- przy każdym wejściu do shella
- ~/.zprofile
- jak zshrc, ale wykonuje się przed nim
- ~/.zshrc
- przy każdym wejściu do interaktywnego shella (aliasy, funkcje, opcje, skróty klawiaturowe itp.)
- ~/.zlogin
- przy wejściu do login shella
- ~/.zlogout
- przy wyjściu z login shella
Większość spośród mnóstwa opcji to flagi, do których ustawiania i anulowania służą polecenia setopt opcja
i unsetopt opcja
, a pełną listę pokazuje podręcznik systemowy zshoptions(1)
. Poniżej kilka co ciekawszych:
- print_exit_value
- wyświetla kod błędu polecenia, jeśli jest niezerowy
- append_history
- powłoka przy wyjściu dopisuje swoją historię do pliku historii zamiast nadpisywać plik
Zamiast find
Wzorzec ścieżki do pliku może zawierać sufiks ujęty w nawiasy okrągłe. Polecenie:
ls -d *(x)
pokazuje pliki wykonywalne przez właściciela. Duże X oznacza „wykonywalne przez wszystkich”, inne flagi jak można się domyśleć to np. W (zapisywalne przez wszystkich) czy „r” (dające się odczytać przez właściciela). Ale możliwości jest więcej:
ls -d *(^R) # pliki nie dające się czytać przez wszystkich ls -d *(m0) # pliki zmodyfikowane dzisiaj ls -d *(Lm+2) # pliki o rozmiarze > 2 MB
Podwójna gwiazdka oznacza że będziemy przeszukiwać całe drzewo katalogów, a nie tylko bieżący katalog:
ls **/Makefile chmod 700 **/(/) # tylko katalogi
Bieganie po katalogach
Zsh pozwala nadać etykietkę dowolnemu katalogowi w drzewie katalogów, aby później móc szybko skakać po drzewie:
otocjon=$PWD ... cd ~otocjon
Skróty klawiaturowe
Dość typowa sytuacja: wpisujesz jakieś polecenie, ale żeby dokończyć edycję potrzebujesz dodatkowej informacji którą możesz otrzymać wykonując inne, pomocnicze polecenie powłoki. Naciśnij Alt-Q aby przenieść aktualnie edytowany wiersz do schowka, następnie wprowadź i wykonaj pomocnicze polecenie – natychmiast po jego wykonaniu w wierszu poleceń pojawi się pierwotne polecenie ze schowka, gotowe do edycji.
Alt-A wykonuje bieżące polecenie, po czym w wierszu poleceń pojawia się to samo polecenie gotowe do edycji, z kursorem w tym samym miejscu – przydatne gdy chcemy wielokrotnie wykonać to samo polecenie lub serię podobnych poleceń.
Ctrl-O wykonuje bieżące polecenie i wstawia do bufora następne polecenie z historii – wykonanie tego kilka razy pozwala wykonać ponownie kilka kolejnych poleceń z historii.
Jeśli podczas edycji polecenia zechcesz podejrzeć stronę manuala tego polecenia bez niszczenia zawartości wiersza wprowadzania, użyj Alt-H.
Jeśli nie chcesz rozwijać aktualnego wzorca pliku w poleceniu, ale chcesz zobaczyć co zostanie dopasowane, użyj Ctrl-Xg:
% rm f*^Xg foo foo.c
Powiedzmy, że chcesz wyświetlić poleceniem echo
następujący tekst:
don't do that; type 'rm -rf \*', with a \ before the *.
Oczywiście trzeba go odpowiednio zacytować, ale żeby to zrobić wystarczy użyć kombinacji klawiszy Alt-‚, co spowoduje ujęcie całego aktualnie edytowanego wiersza w cudzysłowy i odpowiednie zacytowanie stosownych znaków łańcucha.
Możesz przypisywać skróty klawiszowe często wykonywanym poleceniom, np. wykonanie:
% bindkey -s '^T' 'uptime > '
spowoduje, że każde naciśnięcie Ctrl-T wykona polecenie uptime
.
Dopełnianie
Wszystkie współczesne powłoki starają się uzupełniać polecenia pod klawiszem TAB, ale zsh wydaje się być w tym zakresie niedościgniony oferując wręcz bizantyńskie możliwości – dopełnienie korzysta z analizy składniowej i kontekstowej już wprowadzonych znaków. Naciśnij klawisz TAB np. w takich kontekstach (podkreślenie symbolizuje pozycję kursora):
kill _[TAB] ls -_[TAB] apt-get install ks_[TAB]
Polecenie:
zstyle ':completion:*' menu select
spowoduje, że po dwukrotnym naciśnięciu TAB przy dopełnianiu będzie można wybrać jedno z dopełnień za pomocą klawiszy kursora.
Jeśli nie odpowiada nam sposób uzupełniania dla danego polecenia lub chcemy zdefiniować uzupełnianie dla własnego polecenia, sięgamy po polecenie compctl
, np. poniższe polecenie powoduje, że podpowiadanym parametrem polecenia compress
będzie dowolny plik inny niż *.Z, chyba że użyto opcji -d
(rozpakuj), wówczas podpowiadany będzie plik pasujący do maski *.Z:
compctl -g '^*.Z' -x 'r[-d,---]' -g '*.Z' -- compress
Zagadnieniem pokrewnym dla dopełniania jest poprawianie literówek. Zobaczmy jak to działa:
% setopt correct % sl zsh: correct 'sl' to 'ls' [nyae]? y % setopt correctall % ls x.v11r4 zsh: correct 'x.v11r4' to 'X.V11R4' [nyae]? n /usr/princton/src/x.v11r4 not found % ls /etc/paswd zsh: correct to '/etc/paswd' to '/etc/passwd' [nyae]? y /etc/passwd
Przekierowania
echo Hello World >file1 >file2 make > make.log | grep Error
Pierwsze polecenie przesyła standardowe wyjście do więcej niż jednego pliku, drugie polecenie przesyła wyjście zarówno do pliku jak i do strumienia. Ze standardowym wejściem też można robić ciekawe rzeczy:
sort <file1 <file2 <file3 cut -d: -f1 /etc/passwd | sort <newnames
Pierwsze polecenie pobiera wejście szeregowo z kilku plików, drugie polecenie pobiera na standardowym wejściu wynik cat
, a następnie zawartość pliku newnames
.
Jeśli chcesz wysłać wyjście zarówno do pliku, jak i na standardowe wyjście, możesz użyć np. takiego polecenia:
echo Hello World >&1 >file1
W zsh, polecenie:
% >file
jest równoważne
% cat >file
natomiast
% <file
oznacza to samo co
% less file
Aliasy
Oprócz zwykłych aliasów, można też definiować aliasy globalne, które działają jak preprocesor w C. Można ich użyć jako skrótów często pisanych nazw użytkowników, hostów itp.
alias -g me=paradox who | grep me alias -g M='| more' who M alias -g W=' | wc -l'
Na nazwy aliasów globalnych zaleca się wybierać napisy składające się z dużych liter – ewentualna pomyłka jest wówczas mało prawdopodobna.
Inne
Zsh jest powłoką rozszerzalną, można pisać własne moduły w C – pełna lista w podręczniku systemowym zshmodules(1)
. Np. aby dodać do shella trochę funkcji matematycznych:
zmodload zsh/mathfunc echo $(( sin(1/4.0)**2 + cos(1/4.0)**2 - 1 ))
Nazwa polecenia poprzedzona znakiem równości rozwija się do pełnej ścieżki tego polecenia (ang. path expansion):
echo =ls(:h)
Polecenie r
powtarza polecenie z opcjonalnymi zmianami:
% echo foo foo % r foo=bar echo bar bar
Polecenie:
vared PATH
pozwala edytować wartość zmiennej.
Zwróć uwagę, że zsh pozwala przywołać wielowierszowe polecenie z historii, i edytować je jak w edytorze pełnotekstowym.
Modyfikatory
Z csh przejęto taką ciekawostkę:
% echo $PWD /home/learning/pf/zsh/zsh2.00/src % echo $PWD:h /home/learning/pf/zsh/zsh2.00 % echo $PWD:h:h /home/learning/pf/zsh % echo $PWD:t src % name=foo.c % echo $name:r foo % echo $name:e c % echo $name:u FOO.C % echo $name:s/foo/bar/ bar.c
Przykładowy plik ~/.zshrc
alias l='ls -dF' PS1=$'%{\e[1;31m%}%~> %{\e[0m%}' RPROMPT='%T' rm () { mv $* /tmp } HISTSIZE=200 HISTFILE=~/.zsh_history SAVEHIST=200 setopt share_history setopt inc_append_history