Execute bash scripts on entering a directory

21,518

Solution 1

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
}

Solution 2

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

Solution 3

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".

Share:
21,518

Related videos on Youtube

James Andino
Author by

James Andino

A Functional Human Being

Updated on September 18, 2022

Comments

  • James Andino
    James Andino almost 2 years

    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.

    • Admin
      Admin almost 13 years
      Into every directory, or selected ones? And the same script for each, or not?
    • Admin
      Admin almost 13 years
      Every directory. The script in the directory named projectSettings.bash if it exists.
  • James Andino
    James Andino over 12 years
    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!
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 12 years
    @JamesAndino In zsh I'd use chpwd. Lacking an exact equivalent in bash, overloading cd feels reasonable. With PROMPT_COMMAND, your per-directory settings will be set later if you run cd foo; somecommand and not at all if you run (cd foo; somecommand) (this may or may not be what you want).
  • James Andino
    James Andino over 12 years
    They do it here using just BASH with out overloading PROMPT_COMMAND or cd github.com/wayneeseguin/rvm I tried to unlock the secret but failed.
  • James Andino
    James Andino over 12 years
    I was completely wrong and apologize. RVM was overloading cd.
  • Michael Mrozek
    Michael Mrozek almost 12 years
    (removed some tangential pro/anti-Ruby stuff from this comment thread)
  • New Alexandria
    New Alexandria over 11 years
    In our work environment we already use aliases to nav to the common repos, thus the last part of this answer is the most useful for us. Thanks!
  • J A
    J A almost 9 years
    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.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 9 years
    @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!
  • J A
    J A almost 9 years
    @Gilles Yeah, you're right.