Exécuter des scripts bash lors de la saisie d'un répertoire

40

Quel est le meilleur moyen d'exécuter un script lors de la saisie dans un répertoire?
Lorsque je déménage dans un nouveau répertoire, j'aimerais que bash exécute le script projectSettings.bash un peu comme le fait RVM.

MageProspero
la source
2
Dans tous les répertoires ou ceux sélectionnés? Et le même script pour chacun, ou pas?
enzotib
Chaque répertoire. Le script dans le répertoire nommé projectSettings.bash s'il existe.
MageProspero
Une question similaire sur Stack Overflow
Gilles 'SO - arrête d'être méchant'

Réponses:

46

Vous pouvez créer cdune fonction (et popet pushd) et la faire détecter si vous entrez dans ce répertoire particulier.

cd () { builtin cd "$@" && chpwd; }
pushd () { builtin pushd "$@" && chpwd; }
popd () { builtin popd "$@" && chpwd; }
unset_all_project_settings () {
  # do whatever it takes to undo the effect of projectSettings.bash,
  # e.g. unset variables, remove PATH elements, etc.
}
chpwd () {
  case $PWD in
    /some/directory|/some/other/directory) . ./projectSettings.bash;;
    *) unset_all_project_settings;;
  esac
}

Ne le faites pas dans des répertoires que vous n'avez pas inscrits sur la liste blanche, car il serait très facile pour quelqu'un de vous faire tromper pour exécuter du code arbitraire - vous envoyer une archive, vous la décompressez ainsi, vous accédez au répertoire qu'il a créé et vous ' Nous allons maintenant exécuter le code de l'attaquant.

Je ne recommande pas cette approche, car cela signifie que le script sera exécuté même si vous entrez dans ce répertoire pour une raison quelconque qui n'est pas liée au travail sur le projet. Je suggère d'avoir une fonction spécifique qui modifie le répertoire du projet et source le script de paramètres.

myproj () {
  cd /some/directory && . ./projectSettings.bash
}
Gilles, arrête de faire le mal
la source
1
J'ai commencé à Ruby il y a peu de temps. L'outil RVM est complètement en Bash et est l'un des meilleurs morceaux de magie Bash que j'ai vu. Je pense que la réponse est un peu idiote, car l’une des choses absolument pires que vous puissiez faire est de rouler sur quelque chose du genre cdet il existe sans aucun doute une meilleure solution. Même utiliser $ PROMPT_COMMAND, c'est mieux!
MageProspero
3
J'avais complètement tort et je m'excuse. RVM surchargeait cd.
MageProspero
5
(Suppression de certains éléments pro / anti-rubis tangentiels de ce fil de commentaire)
Michael Mrozek
1
Dans le fichier projectSettings.bash, je vous suggère d'ajouter une variable d'indicateur pour ne pas répéter l'initialisation si vous quittez / entrez à nouveau le répertoire. Alors tout enfermer dans if [ -z $MYSETTINGS ] ; then export MYSETTINGS=1 ; echo your settings here ; fi. C'est pour éviter les problèmes si vous faites quelque chose comme PATH = / mytools / bin: $ PATH comme type d'initialisation.
araignée
5
@spider Au lieu de cela, il devrait y avoir une sorte de mécanisme non défini si vous quittez le répertoire. Si vous quittez et réentrez, vous devriez récupérer les paramètres!
Gilles, arrête de faire le mal
0

direnv pourrait être ce que vous recherchez.

Voici un exemple tiré de la documentation officielle:

$ cd ~/my_project
$ echo ${FOO-nope}
nope
$ echo export FOO=foo > .envrc
.envrc is not allowed
$ direnv allow .
direnv: reloading
direnv: loading .envrc
direnv export: +FOO
$ echo ${FOO-nope}
foo
$ cd ..
direnv: unloading
direnv export: ~PATH
$ echo ${FOO-nope}
nope
navigaid
la source