Patch-ID: bash41-003
[bash.git] / examples / scripts.v2 / cdhist.bash
blobdf8aea785f77ed7de615bd68c7500e4911efd38e
1 #! /bin/bash
3 # cdhist - cd replacement with a directory stack like pushd/popd
5 # usage: cd [-l] [-n] [-] [dir]
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'
13 # arguments:
14 # dir cd to dir and push dir onto the cd directory stack
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
19 # If the variable CDHISTFILE is set, the cd directory stack is loaded from
20 # and written to $CDHISTFILE every time `cd' is executed.
22 # Note: I got this off the net somewhere; I don't know the original author
24 # Chet Ramey
25 # chet@po.cwru.edu
27 _cd_print()
29 echo -e "$@"
32 cd()
34 typeset -i cdlen i
35 typeset t
37 if [ $# -eq 0 ]
38 then
39 set -- $HOME
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
48 CDHIST[i=i+1]=$t
49 done <$CDHISTFILE
52 if [ "${CDHIST[0]}" != "$PWD" ] && [ -n "$PWD" ]
53 then
54 _cdins # insert $PWD into cd history
57 cdlen=${#CDHIST[*]} # number of elements in history
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
71 -l) # _cdprint directory list
72 ((i=cdlen))
73 while (((i=i-1)>=0))
75 num=$i
76 '_cdprint' "$num ${CDHIST[i]}"
77 done
78 return
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
91 -*) # cd to matched dir in list
92 t=${1#-}
93 i=1
94 while ((i<cdlen))
96 case ${CDHIST[i]} in
97 *$t*)
98 '_cdprint' ${CDHIST[i]}
99 builtin cd ${CDHIST[i]}
101 break
103 esac
104 ((i=i+1))
105 done
106 if ((i>=cdlen))
107 then
108 builtin cd $@
109 # pwd
112 *) # cd to new dir
113 builtin cd $@
114 # pwd
116 esac
118 _cdins # insert $PWD into cd history
120 if [ "$CDHISTFILE" ]
121 then
122 cdlen=${#CDHIST[*]} # number of elements in history
125 while ((i<cdlen))
127 echo ${CDHIST[i]} # update directory history
128 ((i=i+1))
129 done >$CDHISTFILE
133 _cdins() # insert $PWD into cd history
134 { # meant to be called only by cd
135 typeset -i i
139 while (( i < ${#CDHIST[*]} )) # see if dir is already in list
141 if [ "${CDHIST[$i]}" = "$PWD" ]
142 then
143 break
145 ((i=i+1))
146 done
148 if (( i>22 )) # limit max size of list
149 then
150 i=22
153 while (((i=i-1)>=0)) # bump old dirs in list
155 CDHIST[i+1]=${CDHIST[i]}
156 done
158 CDHIST[0]=$PWD # insert new directory in list
161 # examples
162 shopt -s expand_aliases
164 # go to known place before doing anything
165 cd /
167 echo CDHIST: "${CDHIST[@]}"
168 for dir in /tmp /bin - -2 -l
170 cd $dir
171 echo CDHIST: "${CDHIST[@]}"
172 echo PWD: $PWD
174 done
176 exit 0