Jaké jsou praktické rozdíly mezi Bash a Zsh?

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

  • Celý tento hubbub, který jste četli, má mnoho společného s ničím. OS přiřadí “ výchozí “ prostředí při vytváření nových uživatelů, není o nic víc. Bash se ‚ nezúčastní pryč, a můžete to použít jako svůj granát nebo jakýkoli jiný granát c naléhavě nabídnuto.
  • Mluvit jako o někom, kdo ‚ použil oba a přistál na bash – jediné, co mě ze zsh opravdu hluboce nespokojilo, bylo jeho rozhodnutí prolomit shodu POSIX, když standard kanonizuje nepochybně špatná rozhodnutí o návrhu způsoby, které usnadňují nedbalý na správnost, když se pokoušíte psát skripty, které musí být kompatibilní s jinými, přísně POSIX-superset skořápkami. Bohužel tato “ jediná věc “ může být docela velká. Ksh93 přesto nezmizí a kdokoli, kdo má vážné bash, by stejně nepoužíval starou verzi 3.x, kterou Apple dodává.
  • Jako návaznost – včera nainstalovaná Catalina, přepnutá na zsh, importovaná bash_history a zkopírovaná přes některé z mých preferovaných aliasů z bash_profile, nic se nezdálo zlomeno. Oceníte všechny zde poskytnuté informace a doufejme, že to pomůže i ostatním.
  • @CharlesDuffy: Dobrý komentář. WRT je “ vážné “ a používá bash version 3.2.57(1): Víte, jestli Apple používá bash pro cokoli “ důležité “ v systému?

Odpověď

Nejprve několik důležitých věcí:

  1. 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.
  2. 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.
  3. 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:

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áte ls 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ích foo*, nejnovějšímu prvnímu.
  • foo*(Lm+1): soubory odpovídající foo*, jejichž velikost je alespoň 1 MB.
  • foo*(N): stejné jako foo*, ale pokud to neodpovídá žádnému souboru, vytvořte prázdný seznam bez ohledu na to nastavení možnosti null_glob (viz výše).
  • *(D): porovnat všechny soubory včetně dot souborů ( kromě . a ..).
  • foo/bar/*(:t) (pomocí modifikátor historie ): soubory v foo/bar, ale pouze se základním názvem souboru. Například pokud existuje a foo/bar/qux.txt, je rozšířen jako qux.txt.
  • foo/bar/*(.:r): Vezměte běžné soubory pod foo/bar a odstraňte příponu. Např. foo/bar/qux.txt je rozšířen jako foo/bar/qux.
  • foo*.odt(e\""REPLY=$REPLY:r.pdf"\"): vezměte seznam souborů odpovídajících foo*.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 nikoli foobar.
  • image<->.jpg(n): všechny .jpg soubory, jejichž základní název je image následovaný číslem, např.image3.jpg a image22.jpg, ale ne image-backup.jpg. Kvalifikátor glob (n) způsobí, že soubory budou uvedeny v číselném pořadí, tj. image9.jpg přijde před image10.jpg (toto můžete nastavit jako výchozí i bez -n s setopt 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 

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:

  1. 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.

  1. Nahrazování procesů není k dispozici.

Substitucí procesu je syntaxe <(...) nebo >(...).

  1. Vestavěné prvky . a source 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í.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *