What is the best way to execute a script when entering into a directory?
When I move into a new directory I would like bash to execute the projectSettings.bash script much like RVM does.
-
2Into every directory, or selected ones? And the same script for each, or not? – enzotib Sep 24 '11 at 19:50
-
Every directory. The script in the directory named projectSettings.bash if it exists. – MageProspero Sep 24 '11 at 19:54
-
Similar question on Stack Overflow – Gilles 'SO- stop being evil' Feb 26 '15 at 23:41
You can make cd
a function (and pop
and pushd
), and make it detect if you enter that particular directory.
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
}
Do not do this in directories that you haven't whitelisted, because it would make it very easy for someone to trick you into running arbitrary code — send you an archive, so you unzip it, change into the directory it created, and you've now run the attacker's code.
I don't recommend this approach, because it means the script will be executed even if you enter that directory for some reason that's unrelated to working on the project. I suggest having a specific function that changes to the project directory and sources the settings script.
myproj () {
cd /some/directory && . ./projectSettings.bash
}
-
1I only started in Ruby a little while ago. The RVM tool tho is completely in Bash and one of the best pieces of Bash magic I have seen. I think the answer is a little silly because one of the absolutely worse things you can ever do is over ride something like
cd
and there is with out doubt a better way. Even using $PROMPT_COMMAND is better! – MageProspero Oct 2 '11 at 23:21 -
3
-
5(removed some tangential pro/anti-Ruby stuff from this comment thread) – Michael Mrozek♦ Jul 25 '12 at 21:04
-
1in the projectSettings.bash I suggest you to add a flag variable to not repeat the initialization in case you exit/re-enter the directory. So enclose everything in
if [ -z $MYSETTINGS ] ; then export MYSETTINGS=1 ; echo your settings here ; fi
. This is to avoid problems in case you do something PATH=/mytools/bin:$PATH kind of initialisation. – spider Sep 18 '15 at 9:57 -
5@spider Rather there should be some kind of unset mechanism if you leave the directory. If you leave and reenter, you should get the settings back! – Gilles 'SO- stop being evil' Sep 18 '15 at 10:11
direnv might be what you are looking for.
Here is an example taken from the official documentation:
$ 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