1#! /bin/bash 2# 3# cdhist - cd replacement with a directory stack like pushd/popd 4# 5# usage: cd [-l] [-n] [-] [dir] 6# 7# options: 8# -l print the cd directory stack, one entry per line 9# - equivalent to $OLDPWD 10# -n cd to nth directory in cd directory stack 11# -s cd to first directory in stack matching (substring) `s' 12# 13# arguments: 14# dir cd to dir and push dir onto the cd directory stack 15# 16# If the new directory is a directory in the stack and the options selected 17# it (-n, -s), the new working directory is printed 18# 19# If the variable CDHISTFILE is set, the cd directory stack is loaded from 20# and written to $CDHISTFILE every time `cd' is executed. 21# 22# Note: I got this off the net somewhere; I don't know the original author 23# 24# Chet Ramey 25# chet@po.cwru.edu 26 27_cd_print() 28{ 29 echo -e "$@" 30} 31 32cd() 33{ 34 typeset -i cdlen i 35 typeset t 36 37 if [ $# -eq 0 ] 38 then 39 set -- $HOME 40 fi 41 42 if [ "$CDHISTFILE" ] && [ -r "$CDHISTFILE" ] # if directory history exists 43 then 44 typeset CDHIST 45 i=-1 46 while read -r t # read directory history file 47 do 48 CDHIST[i=i+1]=$t 49 done <$CDHISTFILE 50 fi 51 52 if [ "${CDHIST[0]}" != "$PWD" ] && [ -n "$PWD" ] 53 then 54 _cdins # insert $PWD into cd history 55 fi 56 57 cdlen=${#CDHIST[*]} # number of elements in history 58 59 case "$@" in 60 -) # cd to new dir 61 if [ "$OLDPWD" = "" ] && ((cdlen>1)) 62 then 63 '_cdprint' ${CDHIST[1]} 64 builtin cd ${CDHIST[1]} 65 pwd 66 else 67 builtin cd "$@" 68 # pwd 69 fi 70 ;; 71 -l) # _cdprint directory list 72 ((i=cdlen)) 73 while (((i=i-1)>=0)) 74 do 75 num=$i 76 '_cdprint' "$num ${CDHIST[i]}" 77 done 78 return 79 ;; 80 -[0-9]|-[0-9][0-9]) # cd to dir in list 81 if (((i=${1#-})<cdlen)) 82 then 83 '_cdprint' ${CDHIST[i]} 84 builtin cd ${CDHIST[i]} 85 pwd 86 else 87 builtin cd $@ 88 # pwd 89 fi 90 ;; 91 -*) # cd to matched dir in list 92 t=${1#-} 93 i=1 94 while ((i<cdlen)) 95 do 96 case ${CDHIST[i]} in 97 *$t*) 98 '_cdprint' ${CDHIST[i]} 99 builtin cd ${CDHIST[i]} 100 pwd 101 break 102 ;; 103 esac 104 ((i=i+1)) 105 done 106 if ((i>=cdlen)) 107 then 108 builtin cd $@ 109 # pwd 110 fi 111 ;; 112 *) # cd to new dir 113 builtin cd $@ 114 # pwd 115 ;; 116 esac 117 118 _cdins # insert $PWD into cd history 119 120 if [ "$CDHISTFILE" ] 121 then 122 cdlen=${#CDHIST[*]} # number of elements in history 123 124 i=0 125 while ((i<cdlen)) 126 do 127 echo ${CDHIST[i]} # update directory history 128 ((i=i+1)) 129 done >$CDHISTFILE 130 fi 131} 132 133_cdins() # insert $PWD into cd history 134{ # meant to be called only by cd 135 typeset -i i 136 137 i=0 138 139 while (( i < ${#CDHIST[*]} )) # see if dir is already in list 140 do 141 if [ "${CDHIST[$i]}" = "$PWD" ] 142 then 143 break 144 fi 145 ((i=i+1)) 146 done 147 148 if (( i>22 )) # limit max size of list 149 then 150 i=22 151 fi 152 153 while (((i=i-1)>=0)) # bump old dirs in list 154 do 155 CDHIST[i+1]=${CDHIST[i]} 156 done 157 158 CDHIST[0]=$PWD # insert new directory in list 159} 160 161# examples 162shopt -s expand_aliases 163 164# go to known place before doing anything 165cd / 166 167echo CDHIST: "${CDHIST[@]}" 168for dir in /tmp /bin - -2 -l 169do 170 cd $dir 171 echo CDHIST: "${CDHIST[@]}" 172 echo PWD: $PWD 173 174done 175 176exit 0 177