Se zprávou, že Catalina použije výchozí Zsh místo Bash , jsem najít spoustu výsledků, které mi říkají o přepínači, a že to může způsobit problémy s shell skripty, ale nejsem dostatečně obeznámen se Zsh, abych věděl, jaké by tyto problémy mohly být.
Moje shell skripty opravdu nejsou to komplikované, ale já jsem Bash používal pouze v systémech macOS a Linux – nulové zkušenosti se Zsh. Může někdo poskytnout jednoduché praktické srovnání nebo konkrétní kameny úrazu, které budu potřebovat vědět, abych mohl začít pracovat na připravenosti na nový shell při vydání Cataliny?
Komentáře
Odpověď
Nejprve několik důležitých věcí:
- Bash nezmizí . Pokud již používáte bash, nic se pro vás nezmění. Změní se jen to, že zsh bude výchozím přihlašovacím shellem pro nové účty, a přesto můžete místo toho vybrat bash.
- Skripty nejsou ovlivněny . Co se změní, je shell pro interaktivní použití, tj. Shell v terminálech (a také několik dalších věcí, které používají přihlašovací shell, například crontabs). Pokud máte skript v souboru s oprávněními ke spuštění, počínaje šebangovou linkou , například
#!/bin/bash
nebo#!/bin/sh
nebo#!/usr/bin/env bash
bude fungovat stejně jako dříve. - Syntaxe Zsh není zcela kompatibilní s bash , ale je to blízko. Mnoho kódu bude i nadále fungovat, například typické aliasy a funkce. Hlavní rozdíly jsou v interaktivních konfiguračních funkcích.
Nyní, za předpokladu, že uvažujete o přepnutí to zsh, což je možnost už léta, zde jsou hlavní rozdíly, se kterými se setkáte. Toto není vyčerpávající seznam!
Hlavní rozdíly pro interaktivní použití
Konfigurační soubory : čte se bash (hlavně) .bashrc
v interaktivních skořápkách bez přihlášení (ale systém MacOS ve výchozím nastavení spouští přihlašovací prostředí v terminálech), .profile
nebo v přihlašovacích skořápkách a .inputrc
. Zsh čte (hlavně) .zshrc
(ve všech interaktivních skořápkách) a .zprofile
(v přihlašovacích skořápkách). To znamená, že nebude použito žádné z vašich přizpůsobení bash: „Budete je muset přenést. Soubory nemůžete jen kopírovat, protože mnoho věcí bude třeba vylepšit.
Vazby kláves používají úplně jinou syntaxi. Bash používá .inputrc
a bind
integrovaný k vázání klíčů na příkazy readline . Zsh používá bindkey
integrované k vázání klíčů na zle widgety . Většina příkazů readline má ekvivalent zsh, ale není to vždy dokonalá ekvivalence.
Když už mluvíme o klávesových zkratkách, pokud používáte Vi (m) jako editor v terminálu, ale ne jako režim příkazového řádku v shellu, všimnete si, že zsh je výchozí režim editace vi, pokud EDITOR
nebo VISUAL
je nastaven na vi
nebo vim
. bindkey -e
přepne do režimu emacs.
Výzva : bash nastaví výzvu (hlavně) z PS1
, která obsahuje zpětné lomítko . Zsh nastaví výzvu hlavně z PS1
, která obsahuje Procento úniků . Funkčnost bash“ s PROMPT_COMMAND
je k dispozici v zsh prostřednictvím precmd
a preexec
zavěšovací funkce . Zsh má více pohodlných mechanismů pro vytváření efektních výzev, včetně mechanismu motivů výzev .
Základní historie příkazového řádku mechanismy (navigace pomocí nahoru / dolů , vyhledávání pomocí Ctrl + R , rozšíření historie o !!
a přátele, poslední odvolání argumentů pomocí Alt + . nebo $_
) fungují stejným způsobem, ale v detailech je spousta rozdílů, příliš mnoho na to, abychom je zde uvedli. Svou .bash_history
můžete zkopírovat do .zsh_history
, pokud jste nezměnili možnost prostředí, která mění formát souboru.
Dokončení : obě skořepiny mají výchozí základní režim dokončení, který většinou dokončí názvy příkazů a souborů, a přepnou do efektního režimu včetně bash_completion
na bash nebo spuštěním compinit
v zsh. Najdete některé příkazy, které bash zvládá lépe a jiné, které zsh zvládají lépe. Zsh je obvykle přesnější, ale někdy se vzdá toho, kde bash dělá něco, co není správné, ale je rozumné. Chcete-li určit možné dokončení příkazu, má zsh tři mechanismy:
- The „starý“ mechanismus dokončení s
compctl
, na který můžete zapomenout. - „ nový “mechanismus dokončení s
compadd
a spoustou funkcí, které začínají podtržítkem a výkonný, ale složitý mechanismus konfigurace uživatele . - emulace do podporuje funkce dokončení bash , které můžete povolit spuštěním
bashcompinit
. Emulace není 100% dokonalá, ale obvykle funguje.
Mnoho z bash „s shopt
nastavení má odpovídající setopt
v zsh.
Zsh doe sn „t považovat #
za výchozí začátek komentáře na příkazovém řádku, pouze ve skriptech (včetně .zshrc
apod.). Chcete-li povolit interaktivní komentáře, spusťte setopt interactive_comments
.
Hlavní rozdíly ve skriptování
(a samozřejmě pro pokročilé uživatele na příkazovém řádku)
V bash má $foo
hodnotu foo
, rozdělí jej na mezery a pro každou část oddělenou mezerou, pokud obsahuje zástupné znaky a odpovídá existujícímu souboru, nahradí vzor seznamem shod. Abyste získali pouze hodnotu foo
, potřebujete "$foo"
. Totéž platí pro substituci příkazů $(foo)
. V zsh je $foo
hodnota foo
a $(foo)
výstup foo
minus jeho poslední nové řádky, až na dvě výjimky. Pokud se slovo stane prázdným z důvodu rozšiřování prázdných nekótovaných proměnných, bude odstraněno (např. a=; b=; printf "%s\n" one "$a$b" three $a$b five
vytiskne one
, prázdný řádek, three
, five
). Výsledek nahrazení nekótovaných příkazů je rozdělen na mezery, ale jednotlivé části nebudou nahrazeny zástupnými znaky.
Bash pole jsou indexována od 0 do (délka-1). Pole Zsh jsou indexována od 1 do délky. S a=(one two three)
je v bash ${a[1]}
two
, ale v zsh je one
. Pokud v bash pouze odkazujete na proměnnou pole bez složených závorek, získáte první prvek, např. $a
je a $a[1]
je one[1]
.V zsh se $a
rozšíří na seznam neprázdných prvků a $a[1]
se rozšíří na první prvek. Podobně v bash je délka pole ${#a}
; to funguje také v zsh, ale můžete to napsat jednodušeji jako $#a
. Indexaci 0 můžete nastavit jako výchozí pomocí setopt ksh_arrays
; tím se také zapne požadavek používat složené závorky k odkazování na prvek pole.
Bash má navíc zástupné vzory například @(foo|bar)
tak, aby odpovídaly foo
nebo bar
, které jsou povoleny pouze u shopt -s extglob
. V zsh můžete povolit tyto vzory pomocí setopt ksh_glob
, ale existuje i jednodušší nativní syntaxe , například (foo|bar)
, z nichž některé vyžadují setopt extended_glob
(do vložte to do svého .zshrc
a je ve výchozím nastavení zapnuto ve funkcích dokončení). **/
pro rekurzivní procházení adresáře je vždy povoleno v zsh.
Ve výchozím nastavení v bash, pokud vzor zástupného znaku neodpovídá žádnému souboru, je ponechán beze změny. Ve výchozím nastavení zsh „se zobrazí chyba, což je obvykle nejbezpečnější nastavení. Pokud chcete příkazu předat zástupný parametr, použijte uvozovky. Na chování bash můžete přepnout pomocí setopt no_nomatch
. Nesouhlasné zástupné vzory můžete místo toho rozšířit pomocí prázdného seznamu pomocí setopt null_glob
.
V bash běží pravá strana potrubí v subshellu. V zsh běží v nadřazeném prostředí, takže můžete psát věci jako somecommand | read output
.
Některé pěkné funkce zsh
Zde je několik pěkných funkcí zsh, které bash nemá ( alespoň ne bez nějakého vážného maziva na lokty). Opět je to jen výběr z těch, které považuji za nejužitečnější.
Glob kvalifikace povolit porovnávání souborů na základě metadat, jako je jejich časové razítko, velikost atd. Umožňují také vyladění výstupu. Syntaxe je poněkud záhadná, ale je velmi pohodlná. Zde je několik příkladů:
-
foo*(.)
: pouze běžné soubory odpovídajícífoo*
a symbolické odkazy na běžné soubory, nikoli adresáře a jiné speciální soubory. -
foo*(*.)
: pouze spustitelné běžné soubory odpovídajícífoo*
. -
foo*(-.)
: pouze běžné soubory odpovídajícífoo*
, nikoli symbolické odkazy a další speciální soubory. -
foo*(-@)
: pouze visící symbolické odkazy odpovídajícífoo*
. -
foo*(om)
: soubory odpovídajícífoo*
seřazené podle data poslední úpravy, od nejnovějšího. Všimněte si, že pokud toto předátels
provede vlastní třídění. To je zvláště užitečné v… -
foo*(om[1,10])
: 10 nejnovějších souborů odpovídajícíchfoo*
, nejnovějšímu prvnímu. -
foo*(Lm+1)
: soubory odpovídajícífoo*
, jejichž velikost je alespoň 1 MB. -
foo*(N)
: stejné jakofoo*
, ale pokud to neodpovídá žádnému souboru, vytvořte prázdný seznam bez ohledu na to nastavení možnostinull_glob
(viz výše). -
*(D)
: porovnat všechny soubory včetně dot souborů ( kromě.
a..
). -
foo/bar/*(:t)
(pomocí modifikátor historie ): soubory vfoo/bar
, ale pouze se základním názvem souboru. Například pokud existuje afoo/bar/qux.txt
, je rozšířen jakoqux.txt
. -
foo/bar/*(.:r)
: Vezměte běžné soubory podfoo/bar
a odstraňte příponu. Např.foo/bar/qux.txt
je rozšířen jakofoo/bar/qux
. -
foo*.odt(e\""REPLY=$REPLY:r.pdf"\")
: vezměte seznam souborů odpovídajícíchfoo*.odt
a nahradit.odt
řetězcem.pdf
(bez ohledu na to, zda soubor PDF soubor existuje).
Zde je několik užitečných zástupných znaků specifických pro zsh .
-
foo*.txt~foobar*
: vše.txt
soubory, jejichž název začínáfoo
, ale nikolifoobar
. -
image<->.jpg(n)
: všechny.jpg
soubory, jejichž základní název jeimage
následovaný číslem, např.image3.jpg
aimage22.jpg
, ale neimage-backup.jpg
. Kvalifikátor glob(n)
způsobí, že soubory budou uvedeny v číselném pořadí, tj.image9.jpg
přijde předimage10.jpg
(toto můžete nastavit jako výchozí i bez-n
ssetopt numeric_glob_sort
).
Zsh poskytuje velmi pohodlné hromadné přejmenování souborů nástroj: funkce zmv
. Navrženo pro .zshrc
:
autoload zmv alias zcp="zmv -C" zln="zmv -L"
Příklad:
zmv "(*).jpeg" "$1.jpg" zmv "(*)-backup.(*)" "backups/$1.$2"
Bash má několik způsobů použití transformací při získávání hodnoty proměnné . Zsh má některé stejné a mnoho dalších .
Zsh má řadu málo praktických funkcí pro změnu adresářů . Zapnutím setopt auto_cd
přejdete na adresář, když zadáte jeho název, aniž byste museli zadávat cd
(toto má dnes také bash). Pomocí formuláře se dvěma argumenty můžete cd
změnit na adresář, jehož název je blízký aktuálnímu adresáři . Například pokud jste /some/where/foo-old/deeply/nested/inside
a chcete přejít na /some/where/foo-new/deeply/nested/inside
, stačí zadat cd old new
.
Chcete-li proměnné přiřadit hodnotu, samozřejmě napište VARIABLE=VALUE
. Chcete-li upravit hodnota proměnné interaktivně, stačí spustit vared VARIABLE
.
Závěrečné doporučení
Zsh přichází s konfiguračním rozhraním, které podporuje několik nejběžnějších nastavení, včetně konzervovaných receptů na věci, jako je vyplnění bez ohledu na velikost písmen. Chcete-li (znovu) spustit toto rozhraní (první řádek není nutný, pokud používáte konfigurační soubor, který upravil zsh-newuser-install
):
autoload -U zsh-newuser-install zsh-newuser-install
Po vybalení z krabice, bez žádného konfiguračního souboru, je mnoho užitečných funkcí zsh z důvodu zpětné kompatibility s verzemi z roku 1990 zakázáno. zsh-newuser-install
navrhuje zapnout některé doporučené funkce.
Na webu existuje mnoho konfiguračních rámců zsh (mnoho z nich je na Githubu ). Mohou být pohodlným způsobem, jak začít s některými výkonnými funkcemi. Odvrácenou stranou mince je, že vás často zablokují v dělání věcí tak, jak to dělá autor, takže někdy vám „znemožní dělat věci tak, jak chcete. Používejte je na své vlastní riziko.
Příručka zsh obsahuje spoustu informací, ale je často psána tak, aby byla stručná a těžko sledovatelná, a obsahuje několik příkladů. Neváhejte hledat vysvětlení a příklady online: pokud použijete pouze část zsh, který je v příručce snadno srozumitelný, vám bude chybět. Dva dobré zdroje jsou seznam adresátů zsh-users a Unix Stack Exchange . rozsáhlou sbírku článků o přechodu na zsh v počítačích Mac najdete na scriptingosx.com a užitečné Ruby skript, který vám přináší historii vašich příkazů , najdete na Githubu.
Komentáře
- Nyní se ‚ zajímám, zda úžasný ctrl-o funguje na zsh. Samozřejmě to nefunguje ‚ na systému Mac OS ani na bash, takže ‚ není pro tuto odpověď nebo web skutečně relevantní. Nelze ‚ t najít žádné informace o ctrl-o v zsh při rychlém online vyhledávání, ale znovu, informace o ctrl-o v bash jsou také všeobecně nepřesné …
- @Jasper Nevěděl jsem ‚, že by to bash měl. Co se týče popisu, Co dělá to samé v zsh s výchozími vazbami kláves.
- Byl jsem rád, že jste zahrnuli “ Některé pěkné funkce zsh “ a úzkostlivě si ji přečtěte, abyste se pokusili pochopit, proč se Apple mohl rozhodnout přejít z extrémně běžného Bash na mnohem méně populární Zsh. Nenašel jsem ‚ vůbec nic, dokonce ani vzdáleně přesvědčivé, abych přepínač ospravedlnil. Je to ‚ zjevně neúplný seznam, ale vynechali jste hlavní rysy Zsh, protože ‚ měli být zřejmé? Co mi tady chybí?
- @CodyGray Nevím ‚ a Apple to ‚ nemá ve zvyku ospravedlnění. Mohlo to mít něco společného se skutečností, že kdyby se situace obrátila, nebyla by ‚ sekce „pěkných bash funkcí“.Nebo to může být tím, že poslední bash bez GPLv3 opravdu stárne , zatímco zsh má liberálnější licenci.
- Chápal jsem, že licence byla v podstatě jediným důvodem. ‚ Je také důvod, proč je bash v systému macOS stále v3. Na ulici se říká, že bash nebude ‚ aktualizován a očekává se, že bude odstraněn, pokud jej koncový uživatel nenainstaluje pomocí brew atd. Můj plán byl přepnout na zsh spíše pro macOS, ale prozatím se bude držet debian.
Odpovědět
Změnit nyní svůj shell a otestujte – není třeba čekat.
chsh -s /bin/zsh
- Všechny skripty, které závisí na
bash
syntaxe stále najde a zavolá bash. - stejný bash od Mojave se dodává na Catalině a migrovaní uživatelé si zachovávají svůj starý shell.
- Mnoho blogů má skvělé zápisy o přesunu souborů preferencí – zde je jeden takový – https://scriptingosx.com/2019/06/moving-to-zsh-part-2-configuration-files/
- Armin proměnil svoji sérii blogů ve správnou knihu s přibližně 22 tis. slovy.
Odhadoval bych také, že 95% uživatelů systému MacOS nepoužívá příkazový řádek a z těch, které to dělají, dalších 95% nebude muset nic významného měnit nebo Všechno. (Vsadím se, že více než 10% z 1% existujících skořápek musí udělat něco jiného než portovat několik řádků do svých souborů .dot)
Vaše výzva se změní a pokud jste ji změnili na bash
, způsob, jak ji změnit na zsh
, není o nic těžší a o nic méně zdokumentovaný než bash.
Novější granáty by se nikdy nedostaly ze země, kdyby rozbily hlavní předměty nebo způsobily bolestivé období adaptace. Pokud chcete zásadnější změnu a opravdu chcete shell, musíte o tom přemýšlet a vyžaduje školení a záměr osvojit si – zkuste ryby .
Komentáře
- Mám konflikt s
fish
. Používám to už dva roky, ale nekompatibilita některých kopií / vložených jednořádků je únavná. Na druhou stranu je to velmi šikovný shell (automatické návrhy bez < kbd > Tab < / kbd > jsou vynikající) - Chtěl jsem milovat ryby, stále chci milovat ryby, ale za deset let mám příliš mnoho konstrukcí skořápky v
ksh
kdykoli skutečně opustit tento fold. Rád bash nechám za sebou a osobně teď plně přijmu zsh. - Jsem ryzí ryzí. Je to opravdu jen další skořápka podobná Unixu, která má o něco menší cruft. (Doslova se říká “ Konečně shell příkazového řádku pro 90. léta “ na domovské stránce.) Jediný nový shell, který V posledních letech jsem viděl, že ve skutečnosti přineslo něco nového do (hlavního) stolu, byl PowerShell, který byl bohužel příliš dlouho omezen na Windows a stále je omezen na .NET. V PowerShellu stále není to mnoho nového, co by ještě ‚ nebylo provedeno, např. v DCL nebo JCL, ale bylo to provedeno (trochu) vkusně.
- @bmike Proč tedy nepoužívat pouze ksh? Apple dodává nejnovější verzi. Já sám jsem bash prorazil už dávno a nevidím důvod, proč bych teď začal používat zsh.
- Tato odpověď vůbec nepopisuje rozdíly mezi bash a zsh ‚ … a já ‚ si nejsem úplně jistý, proč specifikovat, že “ 95% uživatelů systému macOS don ‚ použití příkazového řádku “ je relevantní pro otázku uživatele, který zjevně používá bash.
odpověď
Moje skripty prostředí opravdu nejsou tak složité
Mají vaše shell skripty řádky shebang (začínající #! /bin/bash
nebo podobnými)? Pokud ne, možná jste neúmyslně používali funkci bash, kde spouští skripty bez shebangu pomocí bash. Ostatní skořápky, například pomlčka nebo zsh, to nechávají na operačním systému, který by místo toho obvykle používal /bin/sh
. /bin/sh
v systému macOS je a pravděpodobně zůstane kopií /bin/bash
, ale spuštěním bash s názvem sh
způsobuje odlišné chování. Specifikem je příručka Bash, 6.11 režim Bash POSIX . Některé body:
- Bash zajišťuje nastavení proměnné
POSIXLY_CORRECT
.
Tato proměnná prostředí může ovlivnit chování řady dalších nástrojů, zejména pokud máte nainstalované nástroje GNU.
- Nahrazování procesů není k dispozici.
Substitucí procesu je syntaxe <(...)
nebo >(...)
.
- Vestavěné prvky
.
asource
nehledají název souboru v aktuálním adresáři. argument, pokud nebyl nalezen prohledáním PATH.
Takže pokud váš skript udělal . foo
očekával, že v aktuálním adresáři získá soubor s názvem foo
, který nebude fungovat. Místo toho byste měli udělat . ./foo
.
Jak můžete uhodnout z čísel, existuje mnoho drobných rozdílů v chování bash v režimu POSIX. Nejlépe použijte shebang, pokud chcete pro své skripty použít bash.
Komentáře
- Při kontrole to vypadá, že drtivá většina skriptů prostředí, které jsem vypálil e nebo použijte buď explicitně state / bin / bash v shebangu (velmi málo z nich) nebo state / bin / sh (téměř všechny z nich), takže by to alespoň nemělo být problém. Díky.
- Myslím, že nahrazování procesů je nyní k dispozici. Úspěšně jsem to také zkusil na Catalině. Viz: zsh.sourceforge.net/Intro/intro_7.html
- @Siu stále vyhrál ‚ t help, které používají
/bin/sh
nebo/bin/bash
v shebangu. Zsh je pouze výchozí interaktivní shell, ‚ nenahradil bash všude - @muru Ah, rozumím. Nečetl jsem odpověď pečlivě a myslel jsem si, že autor hovoří o substituci procesu, není k dispozici v
zsh
😅
odpovědi
V duchu zachování jednoduchosti …
Může kdokoli poskytnout jednoduchý praktický srovnání nebo konkrétní kameny úrazu, které budu potřebovat vědět, abych mohl začít pracovat na připravenosti na nový shell, až bude Catalina vydána?
Pokud přemýšlíte o použití nového výchozího prostředí, zvažte:
- Pokud chcete dát Zsh víru a cítit některé rozdíly beze změny nastavení shellu na vašem počítači, můžete zkusit Powerline10k v kontejneru Docker a zjistit, zda je to váš šálek čaje.
- Pokud nepotřebujete všechny zvonky a píšťalky a používat Bash pouze pro základní skripty, je poměrně snadné nastavit si shell, jak zde vysvětlili ostatní. A pokud se rozhodnete chci používat funkce v Bash 5 , je to docela triviální upgrade pro macOS .
- Chcete-li zlepšit přenositelnost svých skriptů, aby s větší pravděpodobností fungovaly podle očekávání v obou skořápkách, otestujte, zda vyhovují předpisům POSIX a odstraňte všechny „bashismy“. K tomu jsem použil ShellCheck a pro méně komplikované skripty to docela dobře funguje.
I když není žádná konkrétní cesta jasná tyto tři přístupy by vám měly poskytnout dostatečnou jistotu, abyste mohli učinit informované rozhodnutí bez nadměrného plánování prostoru problému nebo řešení.
bash version 3.2.57(1)
: Víte, jestli Apple používábash
pro cokoli “ důležité “ v systému?