Tout d'abord, quelques éléments importants :
-
Bash ne va pas disparaître . Si vous utilisez déjà bash, rien ne changera pour vous. Tout ce qui change, c'est que zsh sera l'interpréteur de commandes de connexion par défaut pour les utilisateurs de nouveau et même dans ce cas, vous pouvez choisir bash à la place.
-
Les scripts ne sont pas concernés. . Ce qui change, c'est le shell pour une utilisation interactive, c'est-à-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 permissions d'exécution, commençant par un ligne shebang comme
#!/bin/bash
o #!/bin/sh
o #!/usr/bin/env bash
il continuera à fonctionner exactement comme avant.
- La syntaxe de Zsh n'est pas complètement compatible avec celle de bash, mais elle en est proche. Beaucoup de code continuera à fonctionner, par exemple les alias et fonctions typiques. Les principales différences résident dans les fonctionnalités de configuration interactive.
Maintenant, en supposant que vous envisagiez de passer à zsh, ce qui est une possibilité depuis des années, voici les principales différences que vous rencontrerez. Il ne s'agit pas d'une liste exhaustive !
Principales différences pour une utilisation interactive
Fichiers de configuration : bash lit (principalement) .bashrc
dans les shells interactifs sans login (mais MacOS lance un shell de login dans les terminaux par défaut), .profile
o .bash_profile
dans les shells de connexion, et .inputrc
. Zsh lit (principalement) .zshrc
(dans tous les shells interactifs) et .zprofile
(dans les coquilles de connexion). Cela signifie qu'aucune de vos personnalisations bash ne s'appliquera : vous devrez les porter. Vous ne pouvez pas vous contenter de copier les fichiers car de nombreuses choses devront être modifiées.
Liaisons de touches utilisent une syntaxe complètement différente. Bash utilise .inputrc
et le bind
intégré pour lier les clés à commandes de lecture en ligne . Zsh utilise le site bindkey
intégré pour lier les clés à zle widgets . La plupart des commandes readline ont un équivalent zsh, mais ce n'est pas toujours une équivalence parfaite.
En parlant de liaisons de touches, 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 passe par défaut en mode d'édition vi (c'est-à-dire avec les modes commande et insertion) si EDITOR
o VISUAL
est réglé sur vi
o vim
. bindkey -e
passe en mode emacs (c'est-à-dire où vous pouvez toujours taper directement).
Prompt : bash définit l'invite (principalement) de PS1
qui contient échappements de barres obliques inversées . Zsh définit l'invite principalement à partir de PS1
qui contient pourcentages d'évasion . Bien que les concepts soient similaires, les codes d'échappement sont complètement différents. La fonctionnalité de la fonction PROMPT_COMMAND
est disponible dans zsh via l'option precmd
y preexec
fonctions de crochet . Zsh dispose de plus de mécanismes pratiques pour construire des invites fantaisistes, y compris l'option mécanisme de thème rapide .
L'essentiel historique de la ligne de commande mécanismes (navigation avec Up / Down , chercher avec Ctrl + R l'expansion de l'histoire avec !!
et amis, dernier rappel des arguments avec Alt + . o $_
) fonctionnent de la même manière, mais il existe de nombreuses différences dans les détails, trop nombreuses pour être énumérées ici. Vous pouvez copier votre .bash_history
à .zsh_history
si vous n'avez pas modifié une option du shell qui change le format du fichier.
Achèvement Les deux shells utilisent par défaut un mode de complétion basique qui complète principalement les noms de commandes et de fichiers, et passent à un mode plus sophistiqué en incluant la commande 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 là où bash fait quelque chose qui n'est pas correct mais qui est raisonnable. Pour spécifier les complétions possibles d'une commande, zsh dispose de trois mécanismes :
De nombreuses fonctions de bash shopt
paramètres ont un correspondant setopt
dans zsh.
Zsh ne traite pas #
comme début de commentaire sur la ligne de commande par défaut, seulement dans les scripts (y compris les .zshrc
et autres). Pour activer les commentaires interactifs, exécutez setopt interactive_comments
.
Principales différences pour les scripts
(et pour les utilisateurs expérimentés en ligne de commande bien sûr)
Dans bash, $foo
prend la valeur de foo
le divise au niveau des espaces, et pour chaque partie séparée par des espaces, s'il contient des caractères génériques et correspond à un fichier existant, remplace le motif par la liste des correspondances. Pour obtenir simplement la valeur de foo
vous avez besoin "$foo"
. Il en va de même pour la substitution de commandes $(foo)
. Dans zsh, $foo
est la valeur de foo
y $(foo)
est la sortie de foo
moins ses derniers traits de soulignement, à deux exceptions près. Si un mot devient vide à cause de l'expansion de variables vides non citées, il est supprimé (par ex. a=; b=; printf "%s\n" one "$a$b" three $a$b five
imprime one
une ligne vide, three
, five
). Le résultat d'une substitution de commande non citée est divisé au niveau des espaces, mais les morceaux ne sont pas soumis à une correspondance avec les caractères génériques.
Bash tableaux sont indexés de 0 à (longueur-1). Les tableaux de Zsh sont indexés de 1 à la longueur. Vous pouvez faire de l'indexation 0 la valeur par défaut avec setopt ksh_arrays
. Zsh requiert moins d'accolades (sauf si ksh_arrays
est activé). Par exemple, supposons que a=(first second third "" last)
.
Fonctionnalité
Syntaxe Bash
Syntaxe idiomatique de zsh
Expansion
Premier élément
${a[0]}
$a[1]
first
Deuxième élément
${a[1]}
$a[2]
second
Dernier élément
${a[${#a[@]}-1]}
$a[-1]
last
Longueur
${#a[@]}
$#a
5
Tous les éléments
"${a[@]}"
"${a[@]}"
o "${(@)a}"
first
second
third
(mot vide) last
Tous les éléments non vides
$a
first
second
third
last
Bash a un supplément modèles de caractères génériques comme @(foo|bar)
pour correspondre foo
o bar
qui ne sont activés qu'avec shopt -s extglob
. Dans zsh, vous pouvez activer ces motifs avec setopt ksh_glob
mais il existe aussi un modèle plus simple à utiliser. syntaxe native comme (foo|bar)
dont certains exigent setopt extended_glob
(mettez-le dans votre .zshrc
et il est activé par défaut dans les fonctions d'achèvement). Zsh a **/
pour la traversée récursive des répertoires (comme le fait bash moderne mais pas bash 3.2 qui est livré avec MacOS).
Dans bash, par défaut, si un le motif de remplacement ne correspond pas n'importe quel fichier, il est laissé inchangé. Dans zsh, par défaut, vous obtiendrez une erreur, ce qui est généralement le paramètre le plus sûr. Si vous voulez passer un paramètre joker à une commande, utilisez des guillemets. Vous pouvez passer au comportement de bash avec setopt no_nomatch
. Vous pouvez faire en sorte que les motifs joker non correspondants s'étendent à une liste vide à la place avec setopt null_glob
.
Dans bash, l'option côté droit d'un pipeline s'exécute dans un sous-shell. Dans zsh, il s'exécute dans le shell parent, vous pouvez donc écrire des choses comme somecommand | read output
.
Quelques fonctionnalités intéressantes de zsh
Voici quelques fonctionnalités de zsh que bash n'a pas (du moins pas sans une bonne dose d'huile de coude). Encore une fois, il s'agit juste d'une sélection de celles que je considère comme les plus utiles.
Qualifications mondiales permettent de faire correspondre des fichiers sur la base de métadonnées telles que leur horodatage, leur taille, etc. Ils permettent également de modifier la sortie. La syntaxe est plutôt cryptique, mais elle est extrêmement pratique. Voici quelques exemples :
-
foo*(.)
: uniquement les fichiers réguliers correspondant foo*
et des liens symboliques vers des fichiers ordinaires, et non vers des répertoires et autres fichiers spéciaux.
-
foo*(*.)
: uniquement les fichiers réguliers exécutables correspondant foo*
.
-
foo*(-.)
: uniquement les fichiers réguliers correspondant foo*
mais pas les liens symboliques et autres fichiers spéciaux.
-
foo*(-@)
: seulement les liens symboliques pendants qui correspondent foo*
.
-
foo*(om)
: les fichiers correspondant foo*
triés par date de dernière modification, les plus récents en premier. Notez que si vous passez 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*
le plus récent en premier.
-
foo*(Lm+1)
: fichiers correspondants foo*
dont la taille est d'au moins 1MB.
-
foo*(N)
: même chose que foo*
mais s'il ne correspond à aucun fichier, il produira une liste vide, quel que soit le paramétrage de la directive null_glob
(voir ci-dessus).
-
*(D)
: correspond à tous les fichiers, y compris les fichiers point (sauf .
y ..
).
-
foo/bar/*(:t)
(en utilisant un modificateur d'historique ) : les fichiers dans foo/bar
mais avec seulement le nom de base du fichier. Par exemple, s'il existe un fichier foo/bar/qux.txt
il est développé comme qux.txt
.
-
foo/bar/*(.:r)
: prendre des fichiers réguliers sous foo/bar
et supprimer l'extension. Par exemple foo/bar/qux.txt
est développée comme suit foo/bar/qux
.
-
foo*.odt(e\''REPLY=$REPLY:r.pdf'\')
: prendre la liste des fichiers correspondant foo*.odt
et remplacer .odt
par .pdf
(que le fichier PDF existe ou non).
Voici quelques informations utiles spécifiques à zsh modèles de caractères génériques .
-
foo*.txt~foobar*
: tous .txt
les fichiers dont le nom commence par foo
mais pas foobar
.
-
image<->.jpg(n)
: tous .jpg
dont le nom de base est image
suivi d'un numéro, par exemple image3.jpg
y image22.jpg
mais pas image-backup.jpg
. Le qualificatif glob (n)
fait en sorte que les fichiers soient listés dans l'ordre numérique, c.-à-d. image9.jpg
vient avant image10.jpg
(vous pouvez en faire la valeur par défaut même sans -n
avec setopt numeric_glob_sort
).
A renommage en masse des fichiers zsh fournit un outil très pratique : l'utilitaire zmv
fonction . 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 les façons d'appliquer des transformations lors de la prise de valeur d'une variable . Zsh a certains d'entre eux et bien d'autres encore .
Zsh dispose d'un certain nombre de petites fonctionnalités pratiques pour changer les répertoires . Allumez setopt auto_cd
pour passer à un répertoire lorsque vous tapez son nom sans avoir à taper cd
(bash a aussi cela de nos jours). Vous pouvez utiliser le 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 vous voulez aller à /some/where/foo-new/deeply/nested/inside
il suffit de taper cd old new
.
Pour attribuer une valeur à une variable, on écrit bien sûr VARIABLE=VALUE
. Pour modifier la valeur d'une variable de manière interactive, il suffit d'exécuter vared VARIABLE
.
Conseil final
Zsh est livré avec une interface de configuration qui prend en charge quelques-uns des paramètres les plus courants, y compris des recettes en boîte pour des choses comme la complétion insensible à la casse. Pour (re)lancer cette interface (la première ligne n'est pas nécessaire si vous utilisez un fichier de configuration qui a été édité par zsh-newuser-install
) :
autoload -U zsh-newuser-install
zsh-newuser-install
En l'état, sans aucun fichier de configuration, de nombreuses fonctions utiles de zsh sont désactivées pour assurer la compatibilité avec les versions des années 1990. zsh-newuser-install
suggère quelques fonctionnalités recommandées à activer.
Il existe de nombreux cadres de configuration de zsh sur le web (beaucoup d'entre eux sont sur Github ). Ils peuvent constituer un moyen pratique de démarrer avec des fonctionnalités puissantes. Le revers de la médaille est qu'ils vous enferment souvent dans la façon de faire de l'auteur, ce qui vous empêche parfois de faire les choses comme vous le souhaitez. Utilisez-les à vos risques et périls.
Le manuel de zsh contient beaucoup d'informations, mais il est souvent écrit d'une manière laconique et difficile à suivre, et comporte peu d'exemples. N'hésitez pas à chercher des explications et des exemples en ligne : si vous n'utilisez que la partie de zsh facile à comprendre dans le manuel, vous passerez à côté. Deux bonnes ressources sont la liste de diffusion zsh-users y Unix Stack Exchange . Un site vaste collection d'articles sur le passage à zsh sur le mac peuvent être trouvés sur scriptingosx.com et un script Ruby utile pour emporter votre historique de commandes avec vous peut être trouvé sur Github.