51

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.

4

4 Answers 4

62

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
}
10
  • 1
    I 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! Commented Oct 2, 2011 at 23:21
  • 5
    I was completely wrong and apologize. RVM was overloading cd. Commented Oct 7, 2011 at 14:22
  • 5
    (removed some tangential pro/anti-Ruby stuff from this comment thread) Commented Jul 25, 2012 at 21:04
  • 2
    in 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
    Commented Sep 18, 2015 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! Commented Sep 18, 2015 at 10:11
12

direnv might be what you are looking for.

direnv is an extension for your shell. It augments existing shells with a new feature that can load and unload environment variables depending on the current directory.

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
4

It's my cd function

function cd()
{
    if [ -f .exit.sh ]; then
        source .exit.sh;
    fi

    if [ -z $* ]; then
        builtin cd ~
    else
        builtin cd "$*"
    fi

    if [ -f .enter.sh ]; then
        source .enter.sh;
    fi
}

And then you can write your script in ".enter.sh" or ".exit.sh".

2
  • Replace the whle middle if [ -z $* ] (which breaks if you pass cd more than 1 argument) with one line: builtin cd "$@" Commented Oct 19, 2023 at 15:32
  • With this approach: any evil user can put harmful scripts in some path (ex: inside /tmp ? ) and you will execute whatever command there is inside those harmfull scripts whenever you cd into (or cd from) those path... It is incredibly dangerous. Commented Nov 29, 2023 at 13:19
2

ondir is another alternative to run scripts as you enter directories in a terminal.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .