Traduction automatique
Cet article a été traduit automatiquement depuis la version originale en anglais.
Fichiers de démarrage Zsh : ~/.zprofile vs ~/.zshrc sur macOS et Linux
Si votre terminal semble lent, ou si vos variables d'environnement ne se chargent pas là où vous l'attendez, vous êtes probablement confronté à l'ordre de démarrage de Zsh.
La séparation entre ~/.zprofile et ~/.zshrc est l'une des sources de confusion les plus courantes quand on passe à Zsh, surtout sur macOS, où le comportement par défaut diffère de Linux.
TL;DR
~/.zprofile sert à configurer l'environnement. Il s'exécute une fois par connexion, ce qui sur macOS signifie une fois par onglet de terminal. Mettez-y vos PATH, EDITOR, et les gestionnaires de versions comme fnm ou pyenv.
~/.zshrc sert à la configuration interactive. Il s'exécute chaque fois que vous démarrez un nouveau shell. Mettez-y les alias, les thèmes d'invite, et les raccourcis clavier.
Le flux de démarrage du shell
Pour savoir où placer quoi, il faut savoir quand les fichiers sont chargés. Zsh suit une hiérarchie précise.
Shells de connexion vs shells interactifs
Un shell de connexion est le premier shell obtenu après authentification. Sur macOS, chaque nouvel onglet ou fenêtre de terminal est par défaut un shell de connexion. Sur Linux, ouvrir un terminal lance généralement à la place un shell interactif non-login, ce qui explique une grande partie de la confusion entre plateformes.
Un shell interactif est tout shell dans lequel vous pouvez saisir des commandes.
Voici ce qui se passe réellement quand vous ouvrez un terminal sur macOS :
L'ordre de chargement
~/.zshenv(optionnel). S'exécute pour chaque shell, y compris les scripts non interactifs. N'y mettez ni sortie ni logique lourde — cela peut casser les scripts qui chargent votre configuration. Utilisez-le seulement pour des variables d'environnement qui doivent exister partout, ce qui est rare pour la plupart des gens.~/.zprofile. S'exécute uniquement pour les shells de connexion. C'est votre phase d'initialisation.~/.zshrc. S'exécute pour les shells interactifs. C'est votre phase de personnalisation.~/.zlogin(optionnel). S'exécute tout à la fin du démarrage d'un shell de connexion.
Que mettre où ?
~/.zprofile : la couche environnement
C'est ici que vous configurez ce dont tous les autres processus héritent — chemins, variables, gestionnaires de versions de langage.
Ce qui doit aller ici :
- Modifications de
PATH. - Variables d'environnement :
EDITOR,LANG,GOPATH,JAVA_HOME. - Initialisation d'outils qui modifie l'environnement :
pyenv,rbenv,fnm,cargo.
Ces éléments n'ont besoin d'être calculés qu'une seule fois. Si vous les mettez dans .zshrc, ils seront recalculés à chaque ouverture d'un sous-shell ou exécution d'un script, ce qui fait perdre du temps et peut laisser des entrées en double dans votre PATH.
# ~/.zprofile
# 1. Set up your PATH
# Local bin first so your tools override system ones
export PATH="$HOME/.local/bin:/opt/homebrew/bin:$PATH"
# 2. Global variables
export EDITOR="nvim"
export VISUAL="nvim"
export LANG="en_US.UTF-8"
# 3. Version managers (the heavy ones)
# Doing this here keeps shell startup fast
eval "$(fnm env --use-on-cd)"
eval "$(pyenv init -)"
~/.zshrc : la couche interactive
C'est ici que vous personnalisez le shell dans lequel vous tapez réellement.
Ce qui doit aller ici :
- Alias :
alias g='git'. - Votre invite : Starship, Powerlevel10k, Pure.
- Complétions :
compinit. - Raccourcis clavier :
bindkey. - Options du shell :
setopt autocd,setopt histignorealldups.
Ces éléments n'ont d'importance que lorsqu'un humain est au clavier. Un script exécuté en arrière-plan n'a pas besoin de votre invite ni de vos alias git.
# ~/.zshrc
# 1. Prompt
autoload -Uz promptinit && promptinit
prompt pure
# 2. Aliases
alias ll='ls -lah'
alias g='git'
alias gs='git status'
# 3. Shell options
setopt autocd # cd by typing the directory name
setopt histignorealldups # skip duplicate history entries
setopt share_history # share history across tabs
# 4. Completions
autoload -Uz compinit && compinit
Pourquoi ne pas tout mettre dans un seul fichier ?
Vous vous demandez peut-être : si .zprofile s'exécute en premier, pourquoi ne pas y mettre vos alias et ignorer complètement .zshrc ?
Tout se résume à héritage vs redéfinition.
Les variables d'environnement s'héritent
Quand vous faites export EDITOR="vim" dans un shell parent, chaque processus enfant en hérite : sous-shells, scripts, programmes. Vous le définissez une fois et il se propage dans l'arborescence, c'est pourquoi .zprofile est le bon endroit pour export.
Les alias et fonctions ne s'héritent pas
Des alias comme alias g='git' et les fonctions shell sont locaux au shell courant. Ils ne sont pas transmis aux shells enfants.
Si vous définissez un alias dans .zprofile, il existe dans votre shell de connexion de premier niveau. Dès que vous tapez zsh pour démarrer un sous-shell, ou que vous exécutez un script, cet alias disparaît. Pour avoir des alias partout, vous devez les redéfinir dans chaque nouveau shell interactif. C'est exactement à cela que sert .zshrc.
Les scripts n'ont pas besoin de fonctionnalités humaines
Quand vous exécutez un script shell (./deploy.sh), cela lance un nouveau shell non interactif. Il n'a pas besoin de votre invite, il n'a pas besoin de vos alias git, et il n'a certainement pas envie d'attendre que oh-my-zsh finisse de se charger. Garder la configuration interactive dans .zshrc permet aux scripts de s'exécuter rapidement et proprement, sans laisser fuiter votre personnalisation personnelle.
Pièges courants
Mettre nvm ou pyenv dans .zshrc
Vous ouvrez un nouvel onglet de terminal et il faut deux ou trois secondes avant de pouvoir taper quoi que ce soit. Les gestionnaires de versions ont souvent une initialisation lourde, et .zshrc s'exécute à chaque fois. Déplacez-les dans ~/.zprofile et la latence disparaît.
Un PATH qui grossit
Votre $PATH finit avec les mêmes répertoires listés cinq fois. La cause est presque toujours export PATH="$HOME/bin:$PATH" placé dans .zshrc : à chaque rechargement (source ~/.zshrc) ou sous-shell, le chemin est ajouté à nouveau. Déplacez les définitions de PATH vers ~/.zprofile.
Recharger après des modifications
Les modifications de ~/.zprofile ne s'appliquent pas à votre shell courant, car .zprofile n'est lu qu'à la connexion. Vous pouvez soit fermer l'onglet et en ouvrir un nouveau (l'option la plus simple), soit exécuter source ~/.zprofile manuellement.
Pour .zshrc, faites simplement :
source ~/.zshrc
Une configuration qui fonctionne sur macOS et Linux
Si vous passez d'une machine à l'autre (macOS au travail, Linux à la maison, ou l'inverse), vous allez rencontrer une subtilité. Les terminaux Linux démarrent souvent comme des shells non-login, ce qui signifie qu'ils ignorent complètement ~/.zprofile.
La solution habituelle consiste à charger .zprofile depuis .zshrc quand il n'a pas encore été chargé :
# ~/.zshrc
# On Linux/non-login shells, make sure the environment is set
if [[ -o interactive && ! -o login ]]; then
[[ -f ~/.zprofile ]] && source ~/.zprofile
fi
# ... rest of your interactive config
Résumé
| Fichier | Rôle | Exemples |
|---|---|---|
~/.zshenv |
Variables d'env critiques | ZDOTDIR (utilisateurs avancés uniquement) |
~/.zprofile |
Configuration de l'environnement | PATH, EDITOR, eval "$(pyenv init -)" |
~/.zshrc |
Configuration interactive | alias, prompt, bindkey, compinit |
Deux règles couvrent l'essentiel. Les variables s'héritent dans l'arborescence des processus, donc export doit aller dans .zprofile. Les alias et fonctions ne s'héritent pas, donc ils doivent aller dans .zshrc et être redéfinis pour chaque nouveau shell interactif. Si les nouveaux onglets semblent lents, le coupable est presque toujours un pyenv init ou nvm.sh lourd placé dans .zshrc au lieu de .zprofile.