Quelles sont les différences pratiques entre Bash et Zsh?

Avec la nouvelle que Catalina sera par défaut Zsh au lieu de Bash , je « m trouver beaucoup de résultats qui me parlent du commutateur, et quil peut causer des problèmes avec les scripts shell, mais je ne suis pas assez familier avec Zsh pour savoir quels pourraient être ces problèmes.

Mes scripts shell ne le sont vraiment pas compliqué, mais je nai jamais utilisé Bash que sur macOS et Linux – aucune expérience avec Zsh. Quelquun peut-il fournir une comparaison pratique simple, ou des pierres dachoppement spécifiques que jaurai besoin de connaître, afin que je puisse commencer à travailler pour être prêt pour le nouveau shell lors de la sortie de Catalina?

Commentaires

  • Tout ce brouhaha que vous avez lu ne sert à rien. Le système dexploitation attribue un  » default  » shell lors de la création de nouveaux utilisateurs, aucune raison de plus. Bash nest pas ‘ t en cours loin, et vous pouvez lutiliser comme coquille ou comme lun des autres coquilles c ‘ s utilisé les deux et atterri sur bash – la seule chose qui ma rendu vraiment, profondément mécontent de zsh a été sa décision pour rompre la conformité POSIX lorsque la norme canonise les décisions de conception certes mauvaises de manière à ce quil soit facile de se tromper sur lexactitude lors de la tentative décriture de scripts qui devaient être compatibles avec dautres shells strictement POSIX. Malheureusement, cette  » seule chose  » peut être assez importante. Pourtant, ksh93 nest pas ‘ t disparaître, et quiconque est sérieux au sujet de bash ne ‘ t utiliserait de toute façon pas lancienne version 3.x dApple.
  • En guise de suivi – Catalina installé hier, basculé vers zsh, importé bash_history et copié sur certains de mes alias préférés de bash_profile, rien ne semble sêtre cassé. Japprécie toutes les informations fournies par tout le monde ici et jespère que cela aidera aussi les autres.
  • @CharlesDuffy: Bon commentaire. WRT étant  » sérieux  » et utilisant bash version 3.2.57(1): savez-vous si Apple utilise bash pour tout  » important  » sur le système?

Réponse

Tout dabord, quelques points importants:

  1. Bash ne disparaîtra pas . Si vous utilisez déjà bash, rien ne changera pour vous. Tout ce qui change, cest que zsh sera le shell de connexion par défaut pour les nouveaux comptes, et même dans ce cas, vous pouvez sélectionner bash à la place.
  2. Les scripts ne sont pas affectés . Ce qui change, cest le shell pour une utilisation interactive, cest-à-dire le shell dans les terminaux (et aussi quelques autres choses qui utilisent le shell de connexion, comme les crontabs). Si vous avez un script dans un fichier avec des autorisations dexécution, commençant par une ligne shebang telle que #!/bin/bash ou #!/bin/sh ou #!/usr/bin/env bash, il « continuera à fonctionner exactement comme avant.
  3. La syntaxe de

  4. Zsh » nest pas entièrement compatible avec bash , mais cest proche. Beaucoup de code continuera à fonctionner, par exemple les alias et les fonctions typiques. Les principales différences sont dans les fonctionnalités de configuration interactives.

Maintenant, en supposant que vous envisagez de changer à zsh, qui est une possibilité depuis des années, voici les principales différences que vous rencontrerez. Cette liste nest pas exhaustive!

Principales différences pour une utilisation interactive

Fichiers de configuration : bash lit (principalement) .bashrc dans les shells interactifs sans connexion (mais macOS démarre un shell de connexion dans les terminaux par défaut), .profile ou dans les shells de connexion et .inputrc. Zsh lit (principalement) .zshrc (dans tous les shells interactifs) et .zprofile (dans les shells de connexion). Cela signifie quaucune de vos personnalisations bash ne sappliquera: vous devrez les porter. Vous ne pouvez pas simplement copier les fichiers car beaucoup de choses devront être peaufinées.

Les raccourcis clavier utilisent une syntaxe complètement différente. Bash utilise .inputrc et le bind intégré pour lier les clés à commandes readline . Zsh utilise le bindkey intégré pour lier les clés aux widgets zle . La plupart des commandes readline ont un équivalent zsh, mais ce nest pas toujours une équivalence parfaite.

En parlant de raccourcis clavier, si vous utilisez Vi (m) comme éditeur dans le terminal mais pas comme mode de ligne de commande dans le shell, vous remarquerez que zsh utilise par défaut le mode dédition vi si EDITOR ou VISUAL est défini sur vi ou vim . bindkey -e passe en mode emacs.

Invite : bash définit linvite (principalement) de PS1 qui contient échappement de la barre oblique inverse . Zsh définit linvite principalement à partir de PS1 qui contient pourcent séchappe . La fonctionnalité de bash » s PROMPT_COMMAND est disponible dans zsh via precmd et preexec fonctions de crochet . Zsh a plus de mécanismes pratiques pour créer des invites sophistiquées, y compris un mécanisme de thème dinvite .

Le historique de la ligne de commande mécanismes (navigation avec Haut / Bas , recherche avec Ctrl + R , extension de lhistorique avec !! et amis, rappel du dernier argument avec Alt + . ou $_) fonctionnent de la même manière, mais il y a beaucoup de différences dans les détails, trop nombreuses pour être énumérées ici. Vous pouvez copier votre .bash_history vers .zsh_history si vous navez « pas changé une option de shell qui change le format de fichier.

Achèvement : les deux shells utilisent par défaut un mode de complétion de base qui complète principalement les noms de commandes et de fichiers, et passent en mode sophistiqué en y compris bash_completion sur bash ou en exécutant compinit dans zsh. Vous trouverez des commandes que bash gère mieux et d’autres que zsh gère mieux. Zsh est généralement plus précis, mais abandonne parfois où bash fait quelque chose qui nest pas correct mais qui est raisonnable. Pour spécifier les complétions possibles pour une commande, zsh a trois mécanismes:

De nombreux shopt paramètres de bash « s ont un setopt dans zsh.

Zsh doe sn « t traiter # comme un commentaire commençant sur la ligne de commande par défaut, uniquement dans les scripts (y compris .zshrc et autres). Pour activer les commentaires interactifs, exécutez setopt interactive_comments .

Principales différences de script

(et pour les utilisateurs expérimentés sur la ligne de commande bien sûr)

Dans bash, $foo prend la valeur de foo, le divise en caractères despacement, et pour chaque partie séparée par des espaces, sil contient des caractères génériques et correspond à un fichier existant, remplace le modèle par la liste des correspondances. Pour obtenir simplement la valeur de foo, vous avez besoin de "$foo". Il en va de même pour la substitution de commandes $(foo). Dans zsh, $foo est la valeur de foo et $(foo) est la sortie de foo moins ses dernières nouvelles lignes, à deux exceptions près. Si un mot devient vide en raison de lexpansion de variables vides sans guillemets, il est supprimé (par exemple, a=; b=; printf "%s\n" one "$a$b" three $a$b five imprime one, une ligne vide, three, five). Le résultat dune substitution de commande sans guillemets est divisé en espaces, mais les morceaux ne subissent pas de correspondance générique.

Les tableaux sont indexés de 0 à (longueur-1). Les tableaux Zsh sont indexés de 1 à longueur. Avec a=(one two three), en bash, ${a[1]} est two, mais en zsh, cest « s one. Dans bash, si vous référencez simplement une variable de tableau sans accolades, vous obtenez le premier élément, par exemple $a est one et $a[1] est one[1].Dans zsh, $a s’étend à la liste des éléments non vides et $a[1] s’étend au premier élément. De même, dans bash, la longueur dun tableau est ${#a}; cela fonctionne aussi dans zsh mais vous pouvez lécrire plus simplement comme $#a. Vous pouvez définir lindexation 0 par défaut avec setopt ksh_arrays ; cela active également lobligation dutiliser des accolades pour faire référence à un élément de tableau.

Bash a un supplément de motifs génériques tels que @(foo|bar) pour correspondre à foo ou bar, qui ne sont activés quavec shopt -s extglob. Dans zsh, vous pouvez activer ces modèles avec setopt ksh_glob, mais il « existe également un syntaxe native telle que (foo|bar), dont certaines nécessitent setopt extended_glob (do mettez cela dans votre .zshrc, et il est activé par défaut dans les fonctions de complétion). **/ pour la traversée récursive des répertoires est toujours activé dans zsh.

Dans bash, par défaut, si un motif générique ne correspond à aucun fichier, il est à gauche inchangé. Dans zsh, par défaut, vous « obtiendrez une erreur, qui est généralement le paramètre le plus sûr. Si vous voulez passer un paramètre générique à une commande, utilisez des guillemets. Vous pouvez passer au comportement bash avec setopt no_nomatch . Vous pouvez faire en sorte que les modèles de caractères génériques non correspondants deviennent une liste vide à la place avec setopt null_glob .

Dans bash, le côté droit dun pipeline sexécute dans un sous-shell. Dans zsh, il sexécute dans le shell parent, donc vous pouvez écrire des choses comme somecommand | read output.

Quelques fonctionnalités zsh intéressantes

Voici quelques fonctionnalités zsh intéressantes que bash na pas ( du moins pas sans une graisse de coude sérieuse). Encore une fois, ce nest quune sélection de ceux que je considère comme les plus utiles.

Qualificatifs Glob autorise la mise en correspondance des fichiers en fonction des métadonnées telles que leur horodatage, leur taille, etc. Ils permettent également dajuster la sortie. La syntaxe est assez cryptique, mais elle est extrêmement pratique. Voici quelques exemples:

  • foo*(.): seuls les fichiers normaux correspondant à foo* et liens symboliques vers des fichiers normaux, pas vers des répertoires et autres fichiers spéciaux.
  • foo*(*.): uniquement les fichiers exécutables normaux correspondant à foo*.
  • foo*(-.): uniquement les fichiers normaux correspondant à foo*, pas les liens symboliques et autres fichiers spéciaux.
  • foo*(-@): uniquement les liens symboliques pendantes correspondant à foo*.
  • foo*(om): les fichiers correspondant à foo*, triés par date de dernière modification, la plus récente en premier. Notez que si vous transmettez ceci à ls, il « fera son propre tri. Ceci est particulièrement utile dans…
  • foo*(om[1,10]): les 10 fichiers les plus récents correspondant à foo*, les plus récents en premier.
  • foo*(Lm+1): fichiers correspondant à foo* dont la taille est dau moins 1 Mo.
  • foo*(N): identique à foo*, mais si cela ne correspond à aucun fichier, produisez une liste vide malgré tout du paramétrage de loption null_glob (voir ci-dessus).
  • *(D): correspond à tous les fichiers, y compris les fichiers de points ( sauf . et ..).
  • foo/bar/*(:t) (en utilisant un modificateur dhistorique ): les fichiers dans foo/bar, mais avec uniquement le nom de base du fichier. Par exemple, sil y en a a foo/bar/qux.txt, il « est développé comme qux.txt.
  • foo/bar/*(.:r): prenez les fichiers normaux sous foo/bar et supprimez lextension. Par exemple. foo/bar/qux.txt est développé comme foo/bar/qux.
  • foo*.odt(e\""REPLY=$REPLY:r.pdf"\"): prenez le liste des fichiers correspondant à foo*.odt et remplacez .odt par .pdf (que le PDF existe).

Voici quelques modèles de caractères génériques utiles spécifiques à zsh .

  • foo*.txt~foobar*: tous .txt fichiers dont le nom commence par foo mais pas foobar.
  • image<->.jpg(n): tous les fichiers .jpg dont le nom de base est image suivis dun nombre, par exempleimage3.jpg et image22.jpg mais pas image-backup.jpg. Le qualificatif global (n) fait que les fichiers sont répertoriés par ordre numérique, cest-à-dire que image9.jpg vient avant image10.jpg (vous pouvez en faire la valeur par défaut même sans -n avec setopt numeric_glob_sort ).

Pour renommer en masse des fichiers , zsh fournit un outil: la fonction zmv . Suggéré pour votre .zshrc:

autoload zmv alias zcp="zmv -C" zln="zmv -L" 

Exemple:

zmv "(*).jpeg" "$1.jpg" zmv "(*)-backup.(*)" "backups/$1.$2" 

Bash a quelques façons dappliquer des transformations lors de la prise de la valeur dune variable . Zsh a certains des mêmes et bien dautres .

Zsh a un certain nombre de petites fonctionnalités pratiques pour changer de répertoire . Activez setopt auto_cd pour passer à un répertoire lorsque vous saisissez son nom sans avoir à saisir cd (bash la aussi de nos jours). Vous pouvez utiliser la forme à deux arguments pour cd pour passer à un répertoire dont le nom est proche du répertoire actuel . Par exemple, si vous « êtes dans /some/where/foo-old/deeply/nested/inside et que vous souhaitez accéder à /some/where/foo-new/deeply/nested/inside, tapez simplement cd old new.

Pour attribuer une valeur à une variable, il faut bien sûr écrire VARIABLE=VALUE. Pour modifier la valeur dune variable de manière interactive, exécutez simplement vared VARIABLE .

Dernier conseil

Zsh est livré avec une interface de configuration qui prend en charge quelques-uns des paramètres les plus courants, y compris des recettes prédéfinies pour des choses comme la complétion insensible à la casse. Pour (ré) exécuter cette interface (la première ligne nest pas nécessaire si vous « utilisez un fichier de configuration qui a été modifié par zsh-newuser-install):

autoload -U zsh-newuser-install zsh-newuser-install 

Prêt à lemploi, sans fichier de configuration du tout, de nombreuses fonctionnalités utiles de zsh sont désactivées pour une compatibilité descendante avec les versions de 1990. zsh-newuser-install suggère quelques fonctionnalités recommandées à activer.

Il existe de nombreux frameworks de configuration zsh sur le Web (beaucoup dentre eux sont sur Github ). Ils peuvent être un moyen pratique de démarrer avec des fonctionnalités puissantes. Le revers de la médaille est quils vous empêchent souvent de faire les choses comme le fait lauteur, donc parfois ils vous empêcheront de faire les choses comme vous le souhaitez. Utilisez-les à vos risques et périls.

Le Le manuel zsh contient beaucoup dinformations, mais il est souvent écrit dune manière qui « est laconique et difficile à suivre, et il contient peu dexemples. Nhésitez pas à rechercher des explications et des exemples en ligne: si vous nutilisez que la partie de zsh qui est facile à comprendre dans le manuel, vous manquerez. Deux bonnes ressources sont la liste de diffusion zsh-users et Unix Stack Exchange . Une vaste collection darticles sur le passage à zsh sur le mac peut être trouvée sur scriptingosx.com et utile Le script Ruby pour apporter votre historique de commandes avec vous , peut être trouvé sur Github.

Commentaires

  • Maintenant, ‘ je me demande si létonnant ctrl-o fonctionne sur zsh. Bien sûr, cela ne ‘ t fonctionne pas non plus sur Mac OS sur bash, donc cela ‘ nest pas vraiment pertinent pour cette réponse ou ce site. Je nai pas pu ‘ trouver des informations sur ctrl-o dans zsh dans une recherche rapide en ligne, mais là encore, les informations sur ctrl-o dans bash sont également universellement inexactes …
  • @Jasper Je ne savais pas ‘ que bash avait ça. Selon la description, Co fait la même chose dans zsh avec les raccourcis clavier par défaut.
  • Jai été heureux de voir que vous avez inclus les  » Quelques fonctionnalités intéressantes de zsh « , et lisez-la avec impatience pour essayer de comprendre pourquoi Apple a pu prendre la décision de passer du très commun Bash au Zsh, beaucoup moins populaire. Je nai ‘ rien trouvé du tout, même à distance, convaincant pour justifier le changement. Cette ‘ est évidemment une liste non exhaustive, mais avez-vous omis les fonctionnalités principales de Zsh parce quelles ‘ sont censées être évidentes? Que me manque-t-il ici?
  • @CodyGray Je ne ‘ je ne sais pas et Apple n’est pas ‘ dans l’habitude de se justifier. Cela peut avoir quelque chose à voir avec le fait que si la situation avait été inversée, il ny aurait pas ‘ t une section «fonctionnalités de bash intéressantes».Ou cela peut être dû au fait que le dernier bash non GPLv3 vieillit vraiment alors que zsh a une licence plus libérale.
  • Je crois comprendre que la licence était essentiellement la seule raison. Cest ‘ pourquoi bash sur macOS est toujours v3. Le mot dans la rue est que bash a gagné ‘ t être mis à jour et que l’on s’attend à ce qu’il soit supprimé, à moins que l’utilisateur final ne l’installe via brew ou etc. zsh le plus tôt possible pour macOS, mais sen tenir à bash sur Debian pour le moment.

Réponse

Modifier votre shell maintenant et testez – pas besoin dattendre.

chsh -s /bin/zsh 

De plus, j’estimerais que 95% des utilisateurs de macOS n’utilisent pas de ligne de commande et parmi ceux qui le font, 95% n’auront pas à changer quoi que ce soit de significatif ou tout. (Je parierais que 10% des 1% qui savent que les shells existent doivent faire autre chose que porter quelques lignes dans leurs fichiers .dot)

Votre invite changera et si vous avez changé votre invite sur bash, la façon de la modifier sur zsh nest ni plus difficile ni moins documentée que bash.

Les nouveaux obus ne parviendraient jamais à décoller sils cassaient des objets majeurs ou provoquaient une période dadaptation douloureuse. Si vous voulez un changement plus fondamental et voulez vraiment une coquille à laquelle vous devez réfléchir et qui nécessite une formation et une intention d’adopter – essayez fish .

Commentaires

  • Je suis en conflit avec fish. Je lutilise depuis maintenant deux ans mais lincompatibilité de certains one-lines copier / coller est fatigante. Par contre cest un shell très pratique (les suggestions automatiques sans < kbd > Tab < / kbd > sont excellents)
  • Je voulais aimer le poisson, je veux toujours aimer le poisson, mais jai trop de constructions de coquillages dune décennie dans ksh pour jamais vraiment quitter ce pli. Je laisserai volontiers bash derrière moi et embrasserai pleinement zsh maintenant, personnellement.
  • Je suis complètement déçu par les poissons. Cest vraiment juste un autre shell de type Unix avec un peu moins de cruauté. (Il dit littéralement  » Enfin, un shell en ligne de commande pour les années 90  » sur la page daccueil, après tout.) Le seul nouveau shell qui Jai vu ces dernières années apporter quelque chose de nouveau à la table (grand public), cétait PowerShell, qui a malheureusement été confiné à Windows beaucoup trop longtemps et qui est toujours confiné à .NET. Il ny a toujours pas que grand chose de nouveau dans PowerShell qui nait déjà été ‘, par exemple dans DCL ou JCL, mais cela a été fait de manière (un peu) de bon goût.
  • @bmike Pourquoi ne pas utiliser simplement ksh, alors? Apple fournit la version la plus récente. Moi-même, jai lancé bash il y a longtemps et je ne vois aucune raison de commencer à utiliser zsh maintenant.
  • Cette réponse ne ‘ ne décrit pas du tout les différences entre bash et zsh … et je ‘ je ne sais pas trop pourquoi spécifier que  » 95% des utilisateurs de macOS ne ‘ t utiliser la ligne de commande  » est pertinent pour une question dun utilisateur qui utilise évidemment bash.

Réponse

Mes scripts shell ne sont vraiment pas si compliqués

Vos scripts shell ont-ils des lignes shebang (commencent par #! /bin/bash ou similaire)? Sinon, vous avez peut-être involontairement utilisé une fonction bash, où elle exécute des scripts sans shebang en utilisant bash. Dautres shells, comme dash ou zsh, laissent le soin au système dexploitation, qui utiliserait généralement /bin/sh à la place. /bin/sh sur macOS est, et restera probablement, une copie de /bin/bash, mais en exécutant bash avec le nom sh lui donne un comportement différent. Les spécificités sont le manuel Bash, 6.11 Mode Bash POSIX . Quelques points:

  1. Bash garantit que la variable POSIXLY_CORRECT est définie.

Cette variable denvironnement peut affecter le comportement dun certain nombre dautres outils, en particulier si vous avez installé des outils GNU.

  1. La substitution de processus nest pas disponible.

La substitution de processus est la syntaxe <(...) ou >(...).

  1. Les modules internes . et source ne recherchent pas le répertoire actuel pour le nom de fichier argument sil nest pas trouvé en recherchant PATH.

Donc, si votre script a fait . foo vous attendez à ce quil recherche un fichier nommé foo dans le répertoire actuel, cela ne fonctionnera pas. Vous devriez plutôt faire . ./foo.

Comme vous pouvez le deviner daprès les chiffres, il existe de nombreuses différences mineures dans le comportement de bash en mode POSIX. Il est préférable dutiliser un shebang si vous voulez utiliser bash pour vos scripts.

Commentaires

  • En vérifiant, cela ressemble à la grande majorité des scripts shell que jai écrits e ou utilisez explicitement state / bin / bash dans le shebang (très peu dentre eux) ou state / bin / sh (presque tous), de sorte quau moins ne devrait pas être un problème. Merci.
  • Je pense que la substitution de processus est maintenant disponible. Je lai également essayé avec succès sur Catalina. Voir: zsh.sourceforge.net/Intro/intro_7.html
  • @Siu a encore gagné ‘ t scripts daide qui utilisent /bin/sh ou /bin/bash dans le shebang. Zsh nest que le shell interactif par défaut, il na ‘ pas remplacé bash partout
  • @muru Ah, je comprends. Je nai pas lu la réponse attentivement et jai pensé que lauteur parlait de la substitution de processus nest pas disponible dans zsh 😅

Réponse

Dans lesprit de garder les choses simples …

Quelquun peut-il fournir un comparaison, ou des pierres dachoppement spécifiques que jaurai besoin de connaître, afin que je puisse commencer à travailler pour être prêt pour le nouveau shell lorsque Catalina sera publié?

Si vous pensez utiliser le nouveau shell par défaut, considérez:

  • Si vous voulez donner à Zsh un tourbillon et ressentir certaines des différences sans changer les paramètres du shell sur votre machine, vous vous pouvez essayer Powerline10k dans un conteneur Docker et voir si cest votre tasse de thé.
  • Si vous navez pas besoin de toutes les cloches et siffle et utilisez Bash uniquement pour les scripts de base, il est assez facile de configurer votre shell comme dautres ici lont expliqué. Et si vous décidez que vous souhaitez utiliser les fonctionnalités de Bash 5 , cest « une assez mise à jour triviale pour macOS .
  • Si vous souhaitez améliorer la portabilité de vos scripts afin quils « soient plus susceptibles de fonctionner comme prévu dans les deux shells, testez-les pour la conformité POSIX et supprimez tous les « bashismes ». Jai utilisé ShellCheck pour cela et cela fonctionne assez bien pour les scripts moins compliqués.

Bien quaucun chemin particulier ne soit clair ces trois approches devraient vous donner suffisamment de confiance pour prendre une décision éclairée sans trop dingénierie du problème ou de lespace de solution.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *