bashのcdコマンドを履歴で操作できるように拡張する

プロジェクトのディレクトリ構成が階層深くて、ディレクトリの移動がメンドウ。
ディレクりの名前補完ができるのだが、階層が深いので何回もTABを
打たなければならない。
ということで、popd、pushd、dirs、cdを履歴を使って楽に移動できるように
bashのfunctionで拡張した。
ただし、popd、pushdはどっちがどっちだかわからなくなるので、
基本的な使い方は今までのままで。

機能

  • ディレクトリ移動は今まで通り「cd ディレクトリ」
  • 履歴で移動する場合は「cd +番号」
  • 履歴は、dirsで番号付きでディレクトリ単位でソート表示
  • 履歴が大量にある場合は「dg ディレクトリの一部」で検索
  • ログオフ、再ログインしても履歴が残る(履歴をファイルに保存)

使い方

[root@centos5 ~]# cd /var/www/html/
[root@centos5 html]# cd testlink/
[root@centos5 testlink]# cd cfg/
[root@centos5 cfg]# cd /etc/sysconfig/network-scripts/
[root@centos5 network-scripts]# cd /tmp
[root@centos5 tmp]# cd /var/www/html/oc
[root@centos5 oc]# cd /etc
[root@centos5 etc]# dirs
 0  /etc
 3  /etc/sysconfig/network-scripts
 7  /root
 2  /tmp
 6  /var/www/html
 1  /var/www/html/oc
 5  /var/www/html/testlink
 4  /var/www/html/testlink/cfg
[root@centos5 etc]# cd +3
[root@centos5 network-scripts]#

設定

.bashrcに以下を設定

   function cd(){
     builtin pushd ${1:-$HOME} > /dev/null
     cnt=`builtin dirs -v -l |grep ${PWD}$|wc -l`
     if [ $cnt -gt 1 ];then
       popd_num=`builtin dirs -v -l |grep ${PWD}$|tail -1|awk 'BEGIN {FS=" "}{print $1}'`
       builtin popd \+${popd_num} > /dev/null
     fi
   }
  function dirs(){
    if [ $# -eq 0 ]; then
        builtin dirs -v -l|sort -k 2
      fi
    else
      builtin dirs $*
    fi
  }
  function dirsload(){
    if [ ! -f ${HOME}/.bash_dirs ]; then
      touch ${HOME}/.bash_dirs
      return
    fi
    local __PWD=${PWD}
    export FILES=`awk '{print $1}' ${HOME}/.bash_dirs`;
    for FILE in $FILES;
    do
      cd $FILE >/dev/null 2>&1;
    done
    cd ${__PWD}
  }

  function dirssave(){
    if [ ! -f ${HOME}/.bash_dirs ]; then
      touch ${HOME}/.bash_dirs
      return
    fi
    builtin dirs -p -l >>${HOME}/.bash_dirs
    sed "s@^~@`echo ${HOME}`@g" ${HOME}/.bash_dirs|sort |uniq >${HOME}/.bash_dirs.tmp
    cat ${HOME}/.bash_dirs.tmp > ${HOME}/.bash_dirs
    \rm ${HOME}/.bash_dirs.tmp
  }

  alias dg='dirs|grep'

  #.bashrc最後に以下を書くことでログオフ時に履歴を書き込む。
  function exit(){
    dirssave
    builtin exit
  }
  
  ---->8 省略 8<----
  #.bashrc最後に以下を書くことでログイン時に履歴を読み込む。
  dirsload

課題

ログイン時にcdで実際にディレクトリに移動して履歴を設定してるので
履歴が大量にあると時間がかかる。
FILESの環境変数に設定してもdirsに有効にならなかったのでこの方法にした。
もっとスマートな方法がないものだろうか・・・

もし、なにかいい案があれば、コメントか@orange_cloverまで