Push'n'Pop

I really like the directory bookmark/browsing ability of tcsh, when aliasing the pushd command to cd. Using bash, I would naturally like to have the same abilities.

The following listing is of a tcsh session displaying the desired functionality:

$ cd dir3
$ dirs
 0  ~/tmp/dir1/dir2/dir3
 1  ~/tmp/dir1/dir2
 2  ~/tmp/dir1
 3  ~/tmp
$ cd +2
$ pwd
/home/user/tmp/dir1
$ dirs
 0  ~/tmp/dir1
 1  ~/tmp
 2  ~/tmp/dir1/dir2/dir3
 3  ~/tmp/dir1/dir2
$ 

To get the above behavior in tcsh, a few settings needs to be put into the ~/.tcshrc initializations file:

# .tcshrc

alias dirs 'dirs -vl'

set dunique
set pushdsilent 
set pushdtohome 
alias cd 'pushd \!*'

Out of the box, we cannot mimic these tcsh settings in bash, because no counterparts exists. So we need a script:

# .bashrc

alias dirs='dirs -v'
cd() {
   local i MAX LEN p

   MAX=10
   LEN=${#DIRSTACK[@]}

   if [ $# -eq 0 ] || [ "$1" = "-" ]; then
      builtin cd "$@" || return 1
      pushd -n $OLDPWD > /dev/null
   else
      pushd "$@" > /dev/null || return 1
   fi

   if [ $LEN -gt 1 ]; then
      for ((i=1; i <= LEN ; i++)); do
         eval p=~$i
         if [ "$p" = "$PWD" ]; then
            popd -n +$i > /dev/null
            break
         fi
      done
   fi

   if [ $LEN -ge $MAX ]; then
      popd -n -0 > /dev/null
   fi
}

When this function is put into the ~/.bashrc initialization file, the bash cd command behave exactly as it does in tcsh.