]> git.ipfire.org Git - thirdparty/bash.git/blob - examples/scripts.v2/cdhist.bash
df8aea785f77ed7de615bd68c7500e4911efd38e
[thirdparty/bash.git] / examples / scripts.v2 / cdhist.bash
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
32 cd()
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
162 shopt -s expand_aliases
163
164 # go to known place before doing anything
165 cd /
166
167 echo CDHIST: "${CDHIST[@]}"
168 for dir in /tmp /bin - -2 -l
169 do
170 cd $dir
171 echo CDHIST: "${CDHIST[@]}"
172 echo PWD: $PWD
173
174 done
175
176 exit 0