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
Réponse
Tout dabord, quelques points importants:
- 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.
- 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. - 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.
La syntaxe de
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:
- Le « ancien » mécanisme de complétion avec
compctl
que vous pouvez oublier. - Le « nouveau »mécanisme de complétion avec
compadd
et beaucoup de fonctions commençant par un trait de soulignement et un mécanisme de configuration utilisateur puissant mais complexe . - Une émulation pour prend en charge les fonctions de complétion bash que vous pouvez activer en exécutant
bashcompinit
. Lémulation nest pas parfaite à 100% mais elle fonctionne généralement.
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 loptionnull_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 dansfoo/bar
, mais avec uniquement le nom de base du fichier. Par exemple, sil y en a afoo/bar/qux.txt
, il « est développé commequx.txt
. -
foo/bar/*(.:r)
: prenez les fichiers normaux sousfoo/bar
et supprimez lextension. Par exemple.foo/bar/qux.txt
est développé commefoo/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 parfoo
mais pasfoobar
. -
image<->.jpg(n)
: tous les fichiers.jpg
dont le nom de base estimage
suivis dun nombre, par exempleimage3.jpg
etimage22.jpg
mais pasimage-backup.jpg
. Le qualificatif global(n)
fait que les fichiers sont répertoriés par ordre numérique, cest-à-dire queimage9.jpg
vient avantimage10.jpg
(vous pouvez en faire la valeur par défaut même sans-n
avecsetopt 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
- Tous les scripts qui dépendent de
bash
la syntaxe trouvera et appellera toujours bash. - le même bash de Mojave est expédié sur Catalina et les utilisateurs migrés conservent leur ancien shell. / a>
- Armin a transformé sa série de blogs en un véritable livre avec environ 22 000 mots.
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:
- 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.
- La substitution de processus nest pas disponible.
La substitution de processus est la syntaxe <(...)
ou >(...)
.
- Les modules internes
.
etsource
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.
bash version 3.2.57(1)
: savez-vous si Apple utilisebash
pour tout » important » sur le système?