Load Environment on Directory Change
Tags: bash, cloud, programming, tutorial
Published: 2023-08-21 08:34:08

## Change  `gcloud`  context,  `az`  login, Kubernetes context, set environment variables, and more just changing directory

During a typical day at work, I often need to change between two, or even three different repos, each with its relative  `gcloud`, or  `az`, or whatever configuration, its Kubernetes context, and so on.

At the beginning, I find it really frustrating and time-consuming to backward-search in history the commands I needed to run to be able to perform my tasks.

Out of frustration, I decided that I needed to find a way to be able to automate this boring task, and I came up with a simple solution that both saves me a lot of time when I need to switch context, but also helps me to track the steps needed to reach a certain configuration, in case I need to replicate it on another project.

After some stack-overflowing, I created these very simple zsh functions (portable to bash with little to no effort), to load hidden scripts on directory change. In particular, the two functions are named  `cda`  (that stands for  `cd`  and activate, or whatever), and  `sayonara`  (that means  _goodbye_  in Japanese):

```bash
# sourcing hidden files on cd
function cda() {  
        local -a PATHS; PATHS=('.', '.vscode' '.idea')  
        builtin cd "$@" || return  
  
        for p ("$PATHS[@]"); do  
                local hidden="${p}/.hidden.env"  
                if [[ -f "$hidden" ]]  
                then  
                        source $p  
                fi  
        done  
}
 
# Cleaning up when leaving, sourcing actions to do (like deactivate venv)  
function sayonara() {  
        local -a PATHS; PATHS=('.', '.vscode' '.idea')  
  
        for p ("$PATHS[@]"); do  
                local hidden="${p}/.hidden.out.env"  
                if [[ -f "$hidden"]]  
                then  
                        source $p  
                fi  
        done  
  
        if [[ "$#" -gt 0 ]] && local dest=("$@") || local dest=".."  
  
        builtin cd $dest || return  
}  
alias sayo="sayonara"
```

The command  `sayonara`  was also aliased with  `sayo`  for the sake of brevity.

## Why not Just Overriding `cd`?

I  _could_  have named the  `cda`  function  `cd`  and I could have sourced hidden files completely transparently to the user (I am only taking into account the  `cda`  function now, as the other is used more rarely), and initially this was the case. In fact, the  `cda`  function is written in a way that supports exactly this — note that I do not use  `cd`  but  `builtin cd`  instead, otherwise an infinite loop would be caused — but this can cause you problems if you have multiple shells opened, and you visit different directories with a hidden env file.  
Let’s suppose, for example, that you need to work in  `dir1`  with the hidden environment  `env1`  and you’re working on this, but you need to visit code in  `dir2`  with hidden env  `env2`. With the hidden env being sourced on  `cda`, you  `cda`  in  `dir1`, and “only”  `cd`  in  `dir2`, and you have no problems. But, if instead you named the function  `cd`, when you  `cd`  in  `dir1`  `env1`  is sourced, but, when you move to  `dir2`,  `env2`  will be sourced, potentially overriding some configurations of  `env1`  (like the Kubernetes context, or the  `gcloud`  configuration).

Thus, for this problem, I preferred to give up on the dream of writing  `cd`  and having the right configuration always ready to use, and  _“settled”_  for the still very good solution of  `cda`-ing into a directory when I want its environment to be activated, and  `cd`-ing into it when I just want to visit it.