Les variables d'environnement contenant des fonctions sont un hack bash. Zsh n'a rien de similaire. Vous pouvez faire quelque chose de similaire avec quelques lignes de code. Les variables d'environnement contiennent des chaînes; les anciennes versions de bash, avant la découverte de Shellshock , stockaient le code de la fonction dans une variable dont le nom est celui de la fonction et dont la valeur est () {
suivie du code de la fonction suivi de }
. Vous pouvez utiliser le code suivant pour importer des variables avec cet encodage et tenter de les exécuter avec des paramètres de type bash. Notez que zsh ne peut pas émuler toutes les fonctionnalités de bash, tout ce que vous pouvez faire est de vous rapprocher un peu (par exemple, pour $foo
diviser la valeur et étendre les caractères génériques, et créer des tableaux basés sur 0).
bash_function_preamble='
emulate -LR ksh
'
for name in ${(k)parameters}; do
[[ "-$parameters[name]-" = *-export-* ]] || continue
[[ ${(P)name} = '() {'*'}' ]] || continue
((! $+builtins[$name])) || continue
functions[$name]=$bash_function_preamble${${${(P)name}#"() {"}%"}"}
done
(Comme l'a noté Stéphane Chazelas , le découvreur d'origine de Shellshock, une version antérieure de cette réponse pourrait exécuter du code arbitraire à ce stade si la définition de la fonction était incorrecte. Cette version ne fonctionne pas, mais bien sûr dès que vous exécutez une commande, il peut s'agir d'une fonction importée de l'environnement.)
Les versions post-Shellshock des fonctions d'encodage bash dans l'environnement utilisent des noms de variables invalides (par exemple BASH_FUNC_myfunc%%
). Cela les rend plus difficiles à analyser de manière fiable car zsh ne fournit pas d'interface pour extraire ces noms de variables de l'environnement.
Je ne recommande pas de faire ça. Se fier aux fonctions exportées dans les scripts est une mauvaise idée: cela crée une dépendance invisible dans votre script. Si jamais vous exécutez votre script dans un environnement qui n'a pas votre fonction (sur une autre machine, dans une tâche cron, après avoir changé vos fichiers d'initialisation du shell,…), votre script ne fonctionnera plus. Au lieu de cela, stockez toutes vos fonctions dans un ou plusieurs fichiers séparés (quelque chose comme ~/lib/shell/foo.sh
) et démarrez vos scripts en important les fonctions qu'il utilise ( . ~/lib/shell/foo.sh
). De cette façon, si vous modifiez foo.sh
, vous pouvez facilement rechercher les scripts qui en dépendent. Si vous copiez un script, vous pouvez facilement trouver les fichiers auxiliaires dont il a besoin.
Zsh (et ksh avant) rend cela plus pratique en fournissant un moyen de charger automatiquement les fonctions dans les scripts où elles sont utilisées. La contrainte est que vous ne pouvez mettre qu'une seule fonction par fichier. Déclarez la fonction comme chargée automatiquement et placez la définition de la fonction dans un fichier dont le nom est le nom de la fonction. Placez ce fichier dans un répertoire répertorié dans $fpath
(que vous pouvez configurer via la FPATH
variable d'environnement). Dans votre script, déclarez les fonctions chargées automatiquement avec autoload -U foo
.
De plus, zsh peut compiler des scripts, pour gagner du temps d'analyse. Appelez zcompile
pour compiler un script. Cela crée un fichier avec l' .zwc
extension. Si ce fichier est présent autoload
, le fichier compilé sera chargé à la place du code source. Vous pouvez utiliser la zrecompile
fonction pour (re) compiler toutes les définitions de fonction dans un répertoire.