Zsh, czyli dlaczego warto porzucić Basha
16.01.2011 | aktual.: 31.12.2011 15:10
Witam,
Jest to mój pierwszy wpis, więc proszę o wyrozumiałość i/lub sugestie.
Wstęp
Nie podlega wątpliwości, że najpopularniejszą powłoką uniksową jest w dzisiejszych czasach Bash. Wielu użytkowników, również tych doświadczonych, nie zastanawia się, czy nie warto poszukać czegoś lepszego. Tym wpisem chciałbym zachęcić do wypróbowania zsh - moim zdaniem znacznie wygodniejszej alternatywy.
Dlaczego warto spróbować
Na początek chcę zaznaczyć, że zsh jest w dużej mierze kompatybilne z Bashem. Bardzo ułatwia to początki. Większość skryptów powinna działać bez większych przeróbek.
Myślę, że najlepiej będzie jeśli wymienię funkcje, które mi się najbardziej w nim podobają. Bardzo możliwe, że część z nich jest również dostępna w Bashu, ale nie wszystkie. Oto lista:
1) Historia - ignorowane polecenia Osobiście nie lubię robić syfu w historii wpisywanych komend - jeśli nie zamierzam wpisywać jakiejś komendy po raz kolejny, to nie chcę jej tam mieć. By jakoś to kontrolować, mam włączone, że komendy poprzedzone spacją nie trafiają do historii. Niestety w Bashu ta opcja powoduje, że takiej komendy nie można przywołać strzałką do góry nawet tuż po jej wpisaniu. Zsh pamięta ostatnie wpisaną komendę niezależnie od tego, czy trafiła ona do historii. Bardzo pomocne, gdy zrobi się literówkę.
2) Historia, cz. 2 - współdzielenie historii Domyślnie, każda uruchomiona powłoka ma swoją własną historię i zapisuje ją dopiero przy zamknięciu. Ma to pewne poważne konsekwencje. Wyobraźmy sobie taką sytuację: Uruchamiamy powłoki A i B. W A wpisujemy kilka komend i przechodzimy do B. Tam też wpisujemy kilka komend. Zamykamy powłokę A, która zapisuje swoją historię do pliku, nadpisując stary plik z historią nowym. Teraz zamykamy powłokę B, która również... Ups! Chyba straciliśmy polecenia wpisane w powłoce A. Można takich sytuacji uniknąć poprzez dopisywanie nowych poleceń na bieżąco - tuż po ich wywołaniu. Dodatkowo polecam włączyć doczytywanie historii z pliku po każdym poleceniu i gotowe. Mamy kilka uruchomionych powłok, które dzielą jedną historię. Nie ma mowy o zagubionych komendach.
3) Ulepszony globbing
Zakładam, że wszyscy wiedzą co robi ls *, czy ls *.cpp. Niestety, gdy chcemy wyszukać pliki, które mogą być w podkatalogach, pojawia się problem. Można użyć polecenia find, ale jest to niewygodne. W zsh wystarczy użyć **, np. ls **/Makefile znajdzie nam wszystkie pliki Makefile, które znajdują się w obecnym katalogu lub jego podkatalogach. Znacznie bardziej naturalne niż wywołanie find, prawda?
4) Stringi
W Bashu, jeśli mamy zmienną ABC zawierającą tekst "zsh wymiata" i chcemy wyciąć np. 3 znak (h), to musimy posłużyć się następującą konstrukcją: ${ABC:2:1} - wycinamy 1 znak zaczynając od znaku nr 2 (indeksując od 0). Moim zdaniem nie jest to najwygodniejsze. W zsh możemy się posłużyć składnią zbliżoną do C. Zwykłe $ABC[3] wytnie nam trzeci znak (indeksując od 1). Jeśli chcemy dostać jakiś przedział, np. "zsh", wpisujemy $ABC[1,3]. Dodam, że zsh nie akceptuje tutaj składni Basha.
5) Skrócony which
Polecenie which pozwala sprawdzić, gdzie znajduje się dany program lub skrypt. By szybko edytować skrypt o nazwie abc, można wpisać vim `which abc`. W zsh można to zrobić krócej - vim =abc. Oszczędzamy aż 6 klawiszy!
6) Uzupełnianie poleceń Tabem
Uzupełnianie poleceń - nie da się mówić o zsh i nie wspomnieć o nim. Mamy taką sytuację: są pliki plikMój1, plikMój2, plikSiostry. Załóżmy, że chcemy otworzyć plikMój1. Bash uzupełni "plik" i nic nie zrobi, aż nie podamy mu czegoś więcej. Wpisujemy M, wciskamy Tab i musimy jeszcze podać 1 lub 2. Gdy zsh ma kilka podobnych plików, można się pomiędzy nimi przełączać Tabem, a - po odpowiedniej konfiguracji - nawet strzałkami. Nie dotyczy to oczywiście jedynie plików - można nawet uzupełniać sobie procesy w poleceniu kill! Ogólnie, jest to temat-rzeka - ja go tutaj tylko musnąłem.
7) Czepialstwo shella
Tolerancja na zbędne średniki, Bash jej z pewnością nie ma. Przy pisaniu skryptów nie ma to przeważnie znaczenia, ale przy interaktywnym pisaniu pętli czy ifów, już ma. Chcę zrobić np. [code]if [ true ]; then; echo 1; else; echo 2; fi[/code] Czego się dowiaduję od Basha? Po then i else nie powinno być średnika (właściwie, to tego się muszę domyślać z niejasnego komunikatu o błędzie). Czego się dowiaduję od zsh? 1. Wiem, że to ja robię błąd składniowy, ale taki zapis wydaje mi się logiczniejszy.
8) Przechowywanie poleceń na później
Jeśli zaczniemy pisać jakieś dłuższe polecenie i nagle zauważymy, że najpierw musimy zrobić coś innego (np. mkdir), w Bashu mamy problem. W zsh wciskamy Alt+Q. To, co wpisaliśmy, znika. Możemy wywołać jakąś inną komendę, a gdy to zrobimy - nasz Pan Tadeusz wraca na swoje miejsce nietknięty.
Druga strona medalu
Nie mówię, że zsh nie ma wad, bo oczywiście ma. Oto kilka z nich:
1) Przenośność
Bash jest niemal wszędzie. Zsh trzeba doinstalować. Sprawia to, że skrypty nie są aż tak przenośne.
2) Początki
Przy domyślnej konfiguracji, Bash wydaje się wygodniejszy. Zsh jest niemal gołe, mimo kreatora.
3) Szybkość (niepotwierdzone)
Podobno zsh jest nieco wolniejsze. Sam tego nie zauważyłem, ale słyszę takie opinie wśród znajomych.
4) Niedoskonałość uzupełniania (lub użytkownika)
Są rzeczy, które Bash uzupełnia, a zsh nie. Pewnie jest to kwestia ustawień, ale nie byłem w stanie znaleźć sensownego tutoriala do ręcznego poprawiania uzupełnień w zsh. Przykładem jest np. pkill, ale tutaj można się posłużyć killem. EDIT: Tak się zdarzyło, że właśnie wpadł mi w ręce jakiś zrozumiały poradnik pisania funkcji uzupełniania. Już dwie sobie dorobiłem. Dla zainteresowanych - link.
Zakończenie
Każdego, kto spędza dużo czasu w terminalu, zachęcam do wypróbowania zsh. Warto! Jeśli będzie trzeba, mogę wrzucić swój config.
Do studentów wydziału elektroniki na Polibudzie Warszawskiej: to, co widzicie na jednym z wydziałowych serwerów, nie zasługuje na miano zsh. Jest to wersja sprzed wieków i do tego źle skonfigurowana. Jak cały ten serwer. Jeśli to Was odrzuca od zsh, to niech przestanie - na tym syfie sam używam Basha, bo działa lepiej. Jeden kolega właśnie z tego powodu nie chciał przejść na zsh - aż do momentu, gdy pokazałem mu je u siebie.