i-bash/examples/scripts.v2/cdhist.bash
2009-09-12 16:46:56 +00:00

176 lines
2.9 KiB
Bash

#! /bin/bash
#
# cdhist - cd replacement with a directory stack like pushd/popd
#
# usage: cd [-l] [-n] [-] [dir]
#
# options:
# -l print the cd directory stack, one entry per line
# - equivalent to $OLDPWD
# -n cd to nth directory in cd directory stack
# -s cd to first directory in stack matching (substring) `s'
#
# arguments:
# dir cd to dir and push dir onto the cd directory stack
#
# If the new directory is a directory in the stack and the options selected
# it (-n, -s), the new working directory is printed
#
# If the variable CDHISTFILE is set, the cd directory stack is loaded from
# and written to $CDHISTFILE every time `cd' is executed.
#
# Note: I got this off the net somewhere; I don't know the original author
#
# Chet Ramey
# chet@po.cwru.edu
_cd_print()
{
echo -e "$@"
}
cd()
{
typeset -i cdlen i
typeset t
if [ $# -eq 0 ]
then
set -- $HOME
fi
if [ "$CDHISTFILE" ] && [ -r "$CDHISTFILE" ] # if directory history exists
then
typeset CDHIST
i=-1
while read -r t # read directory history file
do
CDHIST[i=i+1]=$t
done <$CDHISTFILE
fi
if [ "${CDHIST[0]}" != "$PWD" ] && [ -n "$PWD" ]
then
_cdins # insert $PWD into cd history
fi
cdlen=${#CDHIST[*]} # number of elements in history
case "$@" in
-) # cd to new dir
if [ "$OLDPWD" = "" ] && ((cdlen>1))
then
'_cdprint' ${CDHIST[1]}
builtin cd ${CDHIST[1]}
pwd
else
builtin cd "$@"
# pwd
fi
;;
-l) # _cdprint directory list
((i=cdlen))
while (((i=i-1)>=0))
do
num=$i
'_cdprint' "$num ${CDHIST[i]}"
done
return
;;
-[0-9]|-[0-9][0-9]) # cd to dir in list
if (((i=${1#-})<cdlen))
then
'_cdprint' ${CDHIST[i]}
builtin cd ${CDHIST[i]}
pwd
else
builtin cd $@
# pwd
fi
;;
-*) # cd to matched dir in list
t=${1#-}
i=1
while ((i<cdlen))
do
case ${CDHIST[i]} in
*$t*)
'_cdprint' ${CDHIST[i]}
builtin cd ${CDHIST[i]}
pwd
break
;;
esac
((i=i+1))
done
if ((i>=cdlen))
then
builtin cd $@
# pwd
fi
;;
*) # cd to new dir
builtin cd $@
# pwd
;;
esac
_cdins # insert $PWD into cd history
if [ "$CDHISTFILE" ]
then
cdlen=${#CDHIST[*]} # number of elements in history
i=0
while ((i<cdlen))
do
echo ${CDHIST[i]} # update directory history
((i=i+1))
done >$CDHISTFILE
fi
}
_cdins() # insert $PWD into cd history
{ # meant to be called only by cd
typeset -i i
i=0
while (( i < ${#CDHIST[*]} )) # see if dir is already in list
do
if [ "${CDHIST[$i]}" = "$PWD" ]
then
break
fi
((i=i+1))
done
if (( i>22 )) # limit max size of list
then
i=22
fi
while (((i=i-1)>=0)) # bump old dirs in list
do
CDHIST[i+1]=${CDHIST[i]}
done
CDHIST[0]=$PWD # insert new directory in list
}
# examples
shopt -s expand_aliases
# go to known place before doing anything
cd /
echo CDHIST: "${CDHIST[@]}"
for dir in /tmp /bin - -2 -l
do
cd $dir
echo CDHIST: "${CDHIST[@]}"
echo PWD: $PWD
done
exit 0