Po wiadomościach, że Catalina domyślnie ustawi Zsh zamiast Bash , znalezienie wielu wyników mówiących o przełączniku i że może powodować problemy ze skryptami powłoki, ale nie jestem wystarczająco zaznajomiony z Zsh, aby wiedzieć, jakie mogą być te problemy.
Moje skrypty powłoki naprawdę nie są to skomplikowane, ale używałem Bash tylko na macOS i Linuksie – zero doświadczenia z Zsh. Czy ktoś może podać proste, praktyczne porównanie lub konkretne przeszkody, które będę musiał znać, abym mógł zacząć pracować nad przygotowaniem się na nowa powłoka, gdy Catalina zostanie wydana?
Komentarze
Odpowiedź
Po pierwsze, kilka ważnych rzeczy:
- Bash nie odchodzi . Jeśli już „używasz basha, nic się dla ciebie nie zmieni. Jedyną zmianą jest to, że zsh będzie domyślną powłoką logowania dla nowych kont, a nawet wtedy możesz zamiast tego wybrać bash.
- Nie dotyczy to skryptów . Jakie zmiany to powłoka do użytku interaktywnego, tj. Powłoka w terminalach (a także kilka innych rzeczy, które używają powłoki logowania, takich jak crontab). Jeśli masz skrypt w pliku z uprawnieniami do wykonywania, zaczynając od linii shebang , na przykład
#!/bin/bash
lub#!/bin/sh
lub#!/usr/bin/env bash
, będzie działać dokładnie tak, jak poprzednio. - Składnia Zsh nie jest w pełni zgodna z bash , ale już blisko. Wiele kodu będzie nadal działać, na przykład typowe aliasy i funkcje. Główne różnice dotyczą interaktywnych funkcji konfiguracyjnych.
Zakładając, że „rozważasz zmianę do zsh, co było możliwe od lat, oto główne różnice, które napotkasz. To nie jest wyczerpująca lista!
Główne różnice w zastosowaniu interaktywnym
Pliki konfiguracyjne : odczyty bash (głównie) .bashrc
w powłokach interaktywnych bez logowania (ale macOS domyślnie uruchamia powłokę logowania w terminalach), .profile
lub w powłokach logowania i .inputrc
. Zsh czyta (głównie) .zshrc
(we wszystkich powłokach interaktywnych) i .zprofile
(w powłokach logowania). Oznacza to, że żadne z Twoich dostosowań basha nie będzie miało zastosowania: „będziesz musiał je przenieść. Nie możesz” po prostu skopiować plików, ponieważ wiele rzeczy będzie wymagało poprawienia.
Klawisze używają zupełnie innej składni. Bash używa .inputrc
i bind
wbudowanego do powiązania kluczy z polecenia readline . Zsh używa bindkey
wbudowanego do wiązania klawiszy z widżetami zle . Większość poleceń readline ma odpowiednik zsh, ale nie zawsze jest to idealny odpowiednik.
Mówiąc o przypisaniach klawiszy, jeśli używasz Vi (m) jako edytora w terminalu, ale nie jako trybu linii poleceń w powłoce, zauważysz, że domyślnym trybem edycji zsh jest vi, jeśli EDITOR
lub VISUAL
jest ustawione na vi
lub vim
. bindkey -e
przełącza się na tryb emacs.
Monituj : bash ustawia podpowiedź (głównie) z PS1
, który zawiera odwrotny ukośnik oznacza . Zsh ustawia znak zachęty głównie z PS1
, który zawiera procent zmiany znaczenia . Funkcjonalność bash” s PROMPT_COMMAND
jest dostępna w zsh przez precmd
i preexec
funkcje podpięcia . Zsh ma więcej wygodnych mechanizmów do tworzenia wymyślnych podpowiedzi, w tym mechanizm motywu podpowiedzi .
Podstawowy historia wiersza poleceń mechanizmy (nawigacja za pomocą W górę / W dół , wyszukiwanie za pomocą Ctrl + R , rozszerzenie historii z !!
i przyjaciółmi, przywołanie ostatniego argumentu za pomocą Alt + . lub $_
) działają w ten sam sposób, ale istnieje wiele różnic w szczegółach, zbyt wiele, aby je tutaj wymienić. Możesz skopiować .bash_history
do .zsh_history
, jeśli nie zmieniłeś opcji powłoki, która zmienia format pliku.
Ukończenie : obie powłoki domyślnie ustawiają się w podstawowym trybie uzupełniania, który w większości uzupełnia nazwy poleceń i plików, i przełączają się na tryb fantazyjny przez włączając bash_completion
na bash lub uruchamiając compinit
w zsh. Znajdziesz kilka poleceń, które lepiej radzą sobie z bashem, a inne lepiej. Zsh jest zwykle bardziej precyzyjne, ale czasami poddaje się, gdy bash robi coś, co nie jest poprawne, ale jest sensowne. Aby określić możliwe uzupełnienia polecenia, zsh ma trzy mechanizmy:
- „stary” mechanizm uzupełniania z
compctl
, o którym można zapomnieć. - „ nowy ”mechanizm uzupełniania z
compadd
i wieloma funkcjami zaczynającymi się od podkreślenia oraz potężny, ale złożony mechanizm konfiguracji użytkownika . - Emulacja do obsługuje funkcje uzupełniania bash , które można włączyć, uruchamiając
bashcompinit
. Emulacja nie jest w 100% idealna, ale zwykle działa.
Wiele ustawień basha shopt
ma odpowiadające im setopt
w zsh.
Zsh doe sn „t traktuj #
jako komentarz, który domyślnie zaczyna się w wierszu poleceń, tylko w skryptach (w tym .zshrc
i tym podobnych). Aby włączyć interaktywne komentarze, uruchom setopt interactive_comments
.
Główne różnice dotyczące skryptów
(i oczywiście dla zaawansowanych użytkowników z wiersza poleceń)
W bashu $foo
przyjmuje wartość foo
dzieli go na białe znaki, a dla każdej części oddzielonej białymi znakami, jeśli zawiera znaki wieloznaczne i pasuje do istniejącego pliku, zastępuje wzorzec listą dopasowań. Aby po prostu uzyskać wartość foo
, potrzebujesz "$foo"
. To samo dotyczy podstawiania poleceń $(foo)
. W zsh $foo
to wartość foo
, a $(foo)
to wynik foo
minus ostatnie znaki nowej linii, z dwoma wyjątkami. Jeśli słowo staje się puste z powodu rozwijania pustych zmiennych niecytowanych, jest usuwane (np. a=; b=; printf "%s\n" one "$a$b" three $a$b five
wyświetla one
, pusty wiersz, three
, five
). Wynik podstawienia niecytowanego polecenia jest dzielony na białe znaki, ale fragmenty nie są dopasowywane za pomocą symboli wieloznacznych.
Bash tablice są indeksowane od 0 do (length-1). Tablice Zsh są indeksowane od 1 do długości. Z a=(one two three)
, w bash, ${a[1]}
to two
, ale w zsh to „s one
. W bash, jeśli odwołasz się tylko do zmiennej tablicowej bez nawiasów klamrowych, otrzymasz pierwszy element, np. $a
to i $a[1]
to one[1]
.W zsh, $a
rozwija się do listy niepustych elementów, a $a[1]
rozwija się do pierwszego elementu. Podobnie, w bash, długość tablicy wynosi ${#a}
; działa to również w zsh, ale możesz napisać to prościej jako $#a
. Możesz ustawić indeksowanie 0 jako domyślne za pomocą setopt ksh_arrays
; włącza to również wymóg używania nawiasów klamrowych do odwoływania się do elementu tablicy.
Bash ma dodatkowe wzorce symboli wieloznacznych , takie jak @(foo|bar)
, aby dopasować foo
lub bar
, które są włączone tylko z shopt -s extglob
. W zsh możesz włączyć te wzorce za pomocą setopt ksh_glob
, ale jest też prostsza metoda natywna składnia , taka jak (foo|bar)
, z których niektóre wymagają setopt extended_glob
(nie umieść to w swoim .zshrc
i jest domyślnie włączone w funkcjach uzupełniania). **/
dla cyklicznego przechodzenia do katalogu jest zawsze włączone w zsh.
Domyślnie w bash, jeśli wzorzec wieloznaczny nie pasuje do żadnego pliku, pozostaje niezmieniony. Domyślnie w zsh pojawi się błąd, który jest zwykle najbezpieczniejszym ustawieniem. Jeśli chcesz przekazać parametr wieloznaczny do polecenia, użyj cudzysłowów. Możesz przełączyć się na zachowanie bash za pomocą setopt no_nomatch
. Zamiast pasujących wzorców symboli wieloznacznych możesz rozwinąć je do pustej listy za pomocą setopt null_glob
.
W bashu prawa strona potoku działa w podpowłoce. W zsh działa w powłoce nadrzędnej, więc możesz napisać takie rzeczy jak somecommand | read output
.
Kilka fajnych funkcji zsh
Oto kilka fajnych funkcji zsh, których bash nie ma ( przynajmniej nie bez poważnego smaru do łokci). Ponownie, to tylko wybór tych, które uważam za najbardziej przydatne.
Kwalifikatory Glob umożliwia dopasowywanie plików na podstawie metadanych, takich jak ich sygnatura czasowa, rozmiar itp. Pozwalają również na modyfikowanie wyników. Składnia jest dość zagadkowa, ale jest niezwykle wygodna. Oto kilka przykładów:
-
foo*(.)
: tylko zwykłe pliki pasujące do i dowiązania symboliczne do zwykłych plików, a nie katalogów i innych plików specjalnych. -
foo*(*.)
: tylko wykonywalne zwykłe pliki pasujące dofoo*
. -
foo*(-.)
: tylko zwykłe pliki pasujące dofoo*
, a nie dowiązania symboliczne i inne pliki specjalne. -
foo*(-@)
: tylko wiszące dowiązania symboliczne pasujące dofoo*
. -
foo*(om)
: pliki pasujące dofoo*
, posortowane według daty ostatniej modyfikacji, od najnowszych. Pamiętaj, że jeśli przekażesz to dols
, wykona własne sortowanie. Jest to szczególnie przydatne w… -
foo*(om[1,10])
: 10 najnowszych plikach pasujących dofoo*
, od najnowszych. -
foo*(Lm+1)
: pliki pasujące dofoo*
o rozmiarze co najmniej 1 MB. -
foo*(N)
: to samo cofoo*
, ale jeśli nie pasuje do żadnego pliku, tworzy pustą listę niezależnie ustawienia opcjinull_glob
(patrz wyżej). -
*(D)
: dopasuj wszystkie pliki, w tym pliki z kropkami ( z wyjątkiem.
i..
). -
foo/bar/*(:t)
(używając modyfikator historii ): pliki wfoo/bar
, ale tylko z podstawową nazwą pliku. Np. jeśli istnieje afoo/bar/qux.txt
, jest rozwijany jakoqux.txt
. -
foo/bar/*(.:r)
: weź zwykłe pliki podfoo/bar
i usuń rozszerzenie. Na przykład.foo/bar/qux.txt
jest rozwinięte jakofoo/bar/qux
. -
foo*.odt(e\""REPLY=$REPLY:r.pdf"\")
: weź listę plików pasujących dofoo*.odt
i zamień.odt
na.pdf
(niezależnie od tego, czy plik PDF plik istnieje).
Oto kilka przydatnych wzorców symboli wieloznacznych specyficznych dla zsh .
-
foo*.txt~foobar*
: all.txt
, których nazwa zaczyna się odfoo
, ale niefoobar
. -
image<->.jpg(n)
: wszystkie.jpg
pliki, których nazwa podstawowa toimage
, po których następuje liczba, np.image3.jpg
iimage22.jpg
, ale nieimage-backup.jpg
. Kwalifikator glob(n)
powoduje, że pliki są wymienione w kolejności numerycznej, tj.image9.jpg
występuje przedimage10.jpg
(możesz ustawić to jako domyślny nawet bez-n
zsetopt numeric_glob_sort
).
pliki masowej zmiany nazw , zsh zapewnia bardzo wygodny narzędzie: funkcja zmv
. Sugerowane dla Twojego .zshrc
:
autoload zmv alias zcp="zmv -C" zln="zmv -L"
Przykład:
zmv "(*).jpeg" "$1.jpg" zmv "(*)-backup.(*)" "backups/$1.$2"
Bash ma kilka sposobów stosowania przekształceń podczas pobierania wartości zmiennej . Zsh ma niektóre z tych samych i wiele innych .
Zsh ma kilka niewielkich wygodnych funkcji do zmiany katalogów . Włącz setopt auto_cd
, aby przejść do katalogu po wpisaniu jego nazwy bez konieczności wpisywania cd
(bash też to ma obecnie). Możesz użyć formularza dwuargumentowego do cd
, aby przejść do katalogu, którego nazwa jest zbliżona do bieżącego katalogu . Na przykład, jeśli jesteś w /some/where/foo-old/deeply/nested/inside
i chcesz przejść do /some/where/foo-new/deeply/nested/inside
, po prostu wpisz cd old new
.
Aby przypisać wartość zmiennej, musisz oczywiście napisać VARIABLE=VALUE
. Aby edytować wartość zmiennej interaktywnie, po prostu uruchom vared VARIABLE
.
Końcowa rada
Zsh jest wyposażony w interfejs konfiguracyjny, który obsługuje kilka najczęściej używanych ustawień, w tym gotowe przepisy na takie rzeczy, jak uzupełnianie bez rozróżniania wielkości liter. Aby (ponownie) uruchomić ten interfejs (pierwsza linia nie jest potrzebna, jeśli „używasz pliku konfiguracyjnego, który został edytowany przez zsh-newuser-install
):
autoload -U zsh-newuser-install zsh-newuser-install
Po wyjęciu z pudełka, bez żadnego pliku konfiguracyjnego, wiele przydatnych funkcji zsh jest wyłączonych w celu zapewnienia zgodności wstecznej z wersjami z lat 90-tych. zsh-newuser-install
sugeruje zalecane funkcje do włączenia.
W sieci jest wiele struktur konfiguracyjnych zsh (wiele z nich to na Github ). Mogą być wygodnym sposobem na rozpoczęcie korzystania z zaawansowanych funkcji. Drugą stroną medalu jest to, że często uniemożliwiają ci robienie rzeczy tak, jak robi to autor, więc czasami uniemożliwiają ci robienie rzeczy tak, jak chcesz. Używaj ich na własne ryzyko.
Podręcznik zsh zawiera wiele informacji, ale często jest napisany w sposób zwięzły i trudny do zrozumienia oraz zawiera kilka przykładów. Nie wahaj się szukać wyjaśnień i przykładów w Internecie: jeśli używasz tylko części zsh, który jest łatwy do zrozumienia w instrukcji, możesz przegapić. Dwa dobre zasoby to lista mailingowa zsh-users i Unix Stack Exchange . obszerną kolekcję artykułów na temat przejścia na zsh na Macu można znaleźć na scriptingosx.com i Skrypt Ruby, który przyniesie ze sobą historię poleceń , można znaleźć na Github.
Komentarze
- Teraz ' zastanawiam się, czy niesamowite ctrl-o działa na zsh. Oczywiście nie ' nie działa również w systemie Mac OS na bash, więc ' nie jest tak naprawdę związane z tą odpowiedzią lub witryną. Nie udało mi się ' znaleźć żadnych informacji o ctrl-o w zsh w szybkim wyszukiwaniu online, ale z drugiej strony informacje o ctrl-o w bash są również powszechnie niedokładne …
- @Jasper Nie ' nie wiedziałem, że bash to ma. Przechodząc do opisu, Co robi to samo w zsh z domyślnymi przypisaniami klawiszy.
- Cieszyłem się, że dołączyłeś ” kilka fajnych funkcji zsh ” i przeczytaj go z niepokojem, aby spróbować zrozumieć, dlaczego firma Apple mogła podjąć decyzję o przejściu z niezwykle popularnego Bash na znacznie mniej popularnego Zsh. Nie ' nie znalazłem w tym miejscu niczego, nawet choćby w niewielkim stopniu przekonującego, aby uzasadnić zmianę. Jest to oczywiście ' lista niewyczerpująca, ale czy pominęliście funkcje nagłówkowe Zsh, ponieważ ' mają być oczywiste? Czego tu brakuje?
- @CodyGray Nie ' nie wiem, a Apple nie ' w przyzwyczajeniu usprawiedliwiania się. Mogło to mieć coś wspólnego z faktem, że gdyby sytuacja została odwrócona, nie byłoby ' sekcji „ładne funkcje basha”.Może tak być, ponieważ ostatnia bash inna niż GPLv3 bardzo się starzeje , podczas gdy zsh ma bardziej liberalną licencję.
- Rozumiem, że licencja była zasadniczo jedynym powodem. ' jest również powodem, dla którego bash w systemie macOS jest nadal w wersji 3. Mówi się, że bash wygrał ' i oczekuje się, że zostanie usunięty, chyba że użytkownik końcowy zainstaluje go za pośrednictwem programu brew itp. Planowałem przejść na zsh raczej wcześniej niż później dla macOS, ale na razie trzymam się bash na Debianie.
Odpowiedź
Zmień teraz swoją powłokę i przetestuj – nie musisz czekać.
chsh -s /bin/zsh
- Wszystkie skrypty zależne od
bash
składnia nadal znajdzie i wywoła bash. - ten sam bash z Mojave jest dostępny w Catalinie, a zmigrowani użytkownicy zachowują swoją starą powłokę.
- Wiele blogów zawiera świetne opisy przenoszenia plików preferencji – oto jeden z nich – https://scriptingosx.com/2019/06/moving-to-zsh-part-2-configuration-files/
- Armin zmienił swoją serię blogów w porządną książkę zawierającą około 22 tys. słów.
Ponadto, szacuję, że 95% użytkowników macOS nie używa wiersza poleceń, a kolejnych 95% nie będzie musiało nic zmieniać wszystko. (Założę się, że 10% z 1% osób, które wiedzą, że powłoki istnieją, musi zrobić coś innego niż przeniesienie kilku wierszy w swoich plikach .dot)
Twój monit ulegnie zmianie i jeśli zmienisz go w bash
, sposób jego zmiany na zsh
nie jest trudniejszy i nie mniej udokumentowany niż bash.
Nowsze muszle nigdy nie oderwałyby się od ziemi, gdyby zepsuły główne elementy lub spowodowały bolesny okres adaptacji. Jeśli chcesz bardziej fundamentalnej zmiany i naprawdę chcesz mieć muszlę, o której musisz pomyśleć i która wymaga przeszkolenia i zamiaru przyjęcia – wypróbuj rybę .
Komentarze
- Mam konflikt z
fish
. Używam go już od dwóch lat, ale niekompatybilność jakiejś kopii / wklejonej jednej linijki jest męcząca. Z drugiej strony jest to bardzo przydatna powłoka (automatyczne sugestie bez < kbd > Tab < / kbd > są doskonałe) - Chciałem kochać ryby, nadal chcę kochać ryby, ale mam zbyt wiele konstrukcji muszli z dekady w
ksh
, aby kiedykolwiek naprawdę opuścić tę fałdę. Chętnie zostawię bash za sobą i osobiście w pełni obejmę zsh. - Jestem całkowicie rozczarowany rybami. Jest to po prostu kolejna powłoka podobna do Uniksa, z trochę mniejszą skorupą. (W końcu na stronie głównej jest napisane dosłownie ” Na koniec powłoka wiersza poleceń z lat 90. „). Jedyna nowa powłoka, która Widziałem w ostatnich latach, że rzeczywiście wprowadził coś nowego do tabeli (głównego nurtu), był PowerShell, który niestety był zbyt długo ograniczony do systemu Windows i nadal jest ograniczony do .NET. Wciąż nie ma tego wiele nowego w PowerShell, które nie ' nie zostało jeszcze zrobione, np. w DCL lub JCL, ale zostało to zrobione w (nieco) gustowny sposób.
- @bmike Dlaczego więc po prostu nie użyć ksh? Apple dostarcza najnowszą wersję. Osobiście zdążyłem już dawno temu spasować bash i nie widzę powodu, by zacząć używać zsh teraz.
- Ta odpowiedź nie ' nie opisuje jednak różnic między bash i zsh … i ja ' nie do końca wiem, dlaczego określam, że ” 95% użytkowników macOS nie ' t użyj wiersza poleceń ” jest istotne w przypadku pytania użytkownika, który oczywiście używa basha.
Odpowiedź
Moje skrypty powłoki naprawdę nie są tak skomplikowane
Czy twoje skrypty powłoki mają linie shebang (zaczynające się od #! /bin/bash
lub podobnego)? Jeśli nie, być może nieumyślnie używasz funkcji bash, która uruchamia skrypty bez shebang za pomocą basha. Inne powłoki, takie jak dash czy zsh, pozostawiają to w gestii systemu operacyjnego, który zwykle używa /bin/sh
. /bin/sh
w systemie macOS jest i prawdopodobnie pozostanie, kopią /bin/bash
, ale wykonuję bash z nazwą sh
powoduje, że zachowuje się inaczej. Szczegóły to podręcznik Bash, 6.11 Tryb Bash POSIX . Kilka punktów:
- Bash zapewnia, że zmienna
POSIXLY_CORRECT
jest ustawiona.
Ta zmienna środowiskowa może wpływać na zachowanie wielu innych narzędzi, zwłaszcza jeśli masz zainstalowane narzędzia GNU.
- Zastępowanie procesów jest niedostępne.
Podstawienie procesu to składnia <(...)
lub >(...)
.
- Funkcje wbudowane
.
isource
nie przeszukują bieżącego katalogu pod kątem nazwy pliku argument, jeśli nie zostanie znaleziony przez wyszukanie PATH.
Więc jeśli twój skrypt . foo
spodziewając się, że będzie źródłem pliku o nazwie foo
w bieżącym katalogu, który nie działa. Zamiast tego należy wykonać . ./foo
.
Jak możesz się domyślić z liczb, istnieje wiele drobnych różnic w zachowaniu basha w trybie POSIX. Najlepiej używaj shebang, jeśli zamierzasz używać basha w swoich skryptach.
Komentarze
- Podczas sprawdzania wygląda na to, że większość skryptów powłoki, które napisałem e lub użyj jawnie state / bin / bash w shebang (bardzo niewielu z nich) lub state / bin / sh (prawie wszystkie z nich), aby przynajmniej nie powinno być problemu. Dzięki.
- Myślę, że zastępowanie procesów jest teraz dostępne. Z powodzeniem wypróbowałem również na Catalinie. Zobacz: zsh.sourceforge.net/Intro/intro_7.html
- @Siu nadal wygrał ' t pomoc dla skryptów, które używają
/bin/sh
lub/bin/bash
w shebang. Zsh jest tylko domyślną powłoką interaktywną, nie ' nie zastąpił bash wszędzie - @muru Ach, rozumiem. Nie przeczytałem uważnie odpowiedzi i pomyślałem, że autor mówi o zastępowaniu procesów nie jest dostępne w
zsh
😅
Odpowiedź
W duchu prostoty …
Czy każdy może podać proste, praktyczne porównanie lub konkretne przeszkody, które będę musiał znać, abym mógł zacząć pracować nad przygotowaniem się na nową powłokę po wydaniu Cataliny?
Jeśli myślisz o użyciu nowej domyślnej powłoki, rozważ:
- Jeśli chcesz dać Zsh wir i poczuć niektóre różnice bez zmiany ustawień powłoki na swojej maszynie, możesz spróbować Powerline10k w kontenerze Dockera i sprawdzić, czy to twoja filiżanka herbaty.
- Jeśli nie potrzebujesz wszystkich dzwonków i gwizdek i używać Bash tylko dla podstawowych skryptów, ustawienie powłoki jest dość łatwe, tak jak wyjaśniły to inne osoby. Jeśli zdecydujesz, że chcesz korzystać z funkcji w Bash 5 , jest to dość trywialna aktualizacja dla macOS .
- Jeśli chcesz poprawić przenośność swoich skryptów, aby „z większym prawdopodobieństwem działały zgodnie z oczekiwaniami w obu powłokach, przetestuj je pod kątem zgodności z POSIX i usuń wszelkie „bashizmy”. Użyłem do tego ShellCheck i działa całkiem dobrze w przypadku mniej skomplikowanych skryptów.
Chociaż żadna konkretna ścieżka nie jest jasna te trzy podejścia powinny dać ci wystarczającą pewność siebie, aby podjąć świadomą decyzję bez nadmiernej inżynierii problemu lub przestrzeni do rozwiązania.
bash version 3.2.57(1)
: czy wiesz, czy Apple używabash
na cokolwiek ” ważne ” w systemie?