Directory dependent history and environment

Carlo Wood, Apr 2007

Table of contents

Introduction

This page describes how to set up cdeh, a set of scripts to automatically switch history and environment (environment variables and aliases) as function of the directory (tree) that you are in.

If, like me, you like working from the command line, and you are using bash as your SHELL, then this is for you.

The type of commands someone gives often depend on the current working directory. Going up through the command line history, it is annoying having to search for the last time you gave that particular command when, in fact, it was probably the last command you gave in a terminal window on that prompt. Also, if you close a terminal, open a new one and change directory back to where you were - you don't want to suddenly have your command history cluttered with unrelated commands.

Especially when you are a developer who works from the command line, like me, it turns out to be very productive to automatically switch environment variables and aliases as function of the project directory that you are in. This makes it possible to create simple aliases for repetive commands that are nearly the same in every project. For example, I configure every project by typing configure; the real command that is executed then depends on the directory I am in. If I am in ~/projects/edragon/edragon-objdir then the actual command is ../edragon/configure --enable-maintainer-mode --enable-debug --prefix=/usr/local/install/4.1.2-20061115 --disable-pch, while if I am in ~/projects/libecc/libecc-objdir then the actual command is ../libecc/configure --enable-maintainer-mode --enable-optimization --enable-debug --prefix=/usr/local/install/4.1.2-20061115. Because these commands seldom change while in the same directory, it is convenient to have a simple alias for them that is a function of the directory that I am in.

How does it work?

The switching is linked to the command prompt: whenever a command line prompt is displayed, the current directory is checked and history/environment switching is performed when necessary. This is achieved through the use of the bash environment variable PROMPT_COMMAND.

The actual history switching is done by changing the bash environment variable that controls the history: HISTFILE. You are free to use the other HIST* environment variables (man bash). The environment variables HISTSIZE and HISTFILESIZE are also used, but if you set them prior to initialization of cdeh, then their values are used.

The environment is changed by sourcing any files in your directory tree that have the name env.source. These files may contain whatever you want. Personally, I use a system to facilitate different C++ projects in different directories, dictating some mandatory content of env.source, but that is basically independent of how cdeh works and is therefore described seperately at the end of this document.

Downloading and setting up cdeh

The cdeh system consists of three system wide files, although it is possible to install them in your home directory if you don't have root.

There are three system wide files. Normally, the environment variable CDEHROOT should be set system wide, and the two files do_prompt and env.bashrc should be installed in CDEHROOT. I also have addhistory (see below) installed in CDEHROOT, and keep a symbolic link from /usr/local/bin to it. The directory $CDEHROOT/history should exist, be owned by root and mode 1777. If you don't have root, then it should exist, be owned by you and be mode 700. For example,

> cd $CDEHROOT
> ls -l
-rwxr-xr-x 1 root staff   93 2007-04-18 17:04 addhistory*
-rwxr-xr-x 1 root staff 3058 2007-04-18 16:31 do_prompt*
-rw-r--r-- 1 root staff 2200 2007-04-18 17:24 env.bashrc
drwxrwxrwt 4 root root  4096 2007-04-18 15:52 history/

The latter needs to be sourced from, for example, your ~/.bashrc file. You can do this by adding the following line at the bottom of your ~/.bashrc file:

HISTSIZE=1200                   # Example, the default is 1000.
CDEHROOT=/encrypted/cdeh        # Or define this globally.
. $CDEHROOT/env.bashrc

Note the leading dot (.).

By picking an encrypted partition for CDEHROOT, all history files will be encrypted. This is the reason that the history files aren't stored in the users home directory by default (which might not be encrypted).

The script do_prompt sources env.source files in the highest directory that one is in. Thus, in any case you will need such a file in the root: /env.source. For now you can just touch it to create an empty file. See below for a practical example.

The small script addhistory should be installed somewhere in your PATH or in CDEHROOT (to keep everything together), using for example a symlink from /usr/local/bin.

Running addhistory inside any directory will start a new history file for that directory and all of it's subdirectories (that do not already have their own history file).

Detailed description

env.bashrc

The following environment variables are set:

do_prompt

This is the main script, executed from PROMPT_COMMAND. There is little to edit in this file, although you might need to be aware of the fact that it starts with setting CDEHTMP again. This should be the same path as is being used in env.bashrc of course.

Nevertheless, the following points probably need your attention:

Example: A system for environment switching

Whenever you change directory, CDEH will descent the directories of the current working directory looking for the first env.source file and source it. For example, if there exists /env.source, /home/carlo/env.source and /home/carlo/projects/libecc/env.source, then changing directory to /home/carlo will source /home/carlo/env.source while changing directory to /home/carlo/projects/libecc/libecc/src will source /home/carlo/projects/libecc/env.source, instead.

Personally, I use the following system for my different C++ projects.

Of course, these are just ideas. Use your creativity and write env.source files that will make your life easier!