df@nud.UUCP (03/26/87)
With the recent discussion on Korn Shell aliases for cd, I thought I'd post my own cd alias. It maintains a directory history in least recently used (LRU) order. You can print the directory history and cd to a recent directory via number or pattern matching. I much prefer it to pushd/popd since the history occurs automatically through the cd command. Optionally, all your shells can share the same directory via a history file, though there is a slight performance hit for this particular feature. Here is an example of its use. ============================================================== $ pwd /usr/df $ cd / $ cd /bin $ cd /usr/bin $ cd -l # "cd -l" lists directory history 3 /usr/df 2 / 1 /bin 0 /usr/bin $ cd -3 # "cd -3" cd's to third most recent directory /usr/df $ cd -l 3 / 2 /bin 1 /usr/bin 0 /usr/df $ cd -bin # "cd -foo" cd's to most recent directory name /usr/bin # containing the string "foo" $ cd -l 3 / 2 /bin 1 /usr/df 0 /usr/bin $ ============================================================== From $HOME/.profile: ============================================================== export CDHISTFILE CDHIST PWD CDHIST=$HOME # CDHISTFILE=$HOME/.cdhistory # set this for directory history file. CDHISTFILE= ENV=$HOME/.kshrc ============================================================== From $HOME/.kshrc (Korn shell ENV file): ============================================================== alias set_prompt="PS1='$ '" # of course, my real prompt is different. alias cd='. $HOME/.functions; _cd' alias md='. $HOME/.functions; md' ============================================================== From $HOME/.functions (Where my function definitions reside): ============================================================== alias cd=_cd function _cd { typeset -i cdlen i typeset t if [ $# -eq 0 ] then set -- $HOME fi if [ "$CDHISTFILE" -a -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" -a "$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 print ${CDHIST[1]} 'cd' ${CDHIST[1]} else 'cd' $@ fi ;; -l) # print directory list typeset -R3 num ((i=cdlen)) while (((i=i-1)>=0)) do num=$i print "$num ${CDHIST[i]}" done return ;; -[0-9]|-[0-9][0-9]) # cd to dir in list if (((i=${1#-})<cdlen)) then print ${CDHIST[i]} 'cd' ${CDHIST[i]} else 'cd' $@ fi ;; -*) # cd to matched dir in list t=${1#-} i=1 while ((i<cdlen)) do case ${CDHIST[i]} in *$t*) print ${CDHIST[i]} 'cd' ${CDHIST[i]} break ;; esac ((i=i+1)) done if ((i>=cdlen)) then 'cd' $@ fi ;; *) # cd to new dir 'cd' $@ ;; esac _cdins # insert $PWD into cd history if [ "$CDHISTFILE" ] then cdlen=${#CDHIST[*]} # number of elements in history i=0 while ((i<cdlen)) do print -r ${CDHIST[i]} # update directory history ((i=i+1)) done >$CDHISTFILE fi set_prompt } function _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 } ============================================================== Cd is a sizable alias, but actually executes quite quickly. I hope it is useful to someone else; I've been using it for several months. -Dale -- seismo!noao!mcdsun!nud!df 602/438-5739 ihnp4!mot!nud!df
ajs@hpfcdt.UUCP (03/31/87)
# Here's yet another way to remember and re-use old directories. This one # remembers everywhere you've been during a login session, and lets you # pick from a sorted menu ("mcd") or list a Pareto-style summary ("lcd"). # I've found it only occasionally useful, but fast and painless. If # nothing else you might find these functions educational. # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by ajs at hpfcdt on Mon Mar 30 16:49:13 1987 # # This archive contains: # ksh.cd # # Error checking via wc(1) will be performed. echo x - ksh.cd cat >ksh.cd <<'@EOF' # ksh functions to remember directory changes and let you pick (from a menu) # directories to which to cd. # Usage: # Read this file with ". file", or put it in your .profile or .kshrc. Then # cd as usual. Say "mcd" to get a menu of places you've been, to pick from. # Say "lcd" to list your cd history, most-visited first. # Warning: Some things don't work right due to ksh deficiencies: # # - The typeset -x below is intended to cause DIRHIST[] to be exported to # subshells. But ksh only exports the first element of any array (and # that's clobbered when mycd() is declared). Too bad. # # - For some reason, the quotes around "$@" in the select in mcd() cause menu # item 1 to be munged sometimes, reason unknown. Remove the quotes if this # is a problem and you never visit a directory with a blank or tab in its # name. # INITIALIZE: # # Note that during .profile, $PWD is not set yet. if [ -z "${DIRHIST:-}" ] # not already set. then DIRHIST="${PWD:-$HOME}" fi typeset -x DIRHIST typeset -x DIRCOUNT=1 # just for fun, how often before. # FUNCTION mycd(): DO A CD AND REMEMBER ALL DIRS VISITED: alias cd=mycd # alias > built-in > function. mycd() { typeset -i dirat=0 # current saved dir index; local var. typeset -i dirs=${#DIRHIST[*]} # number of entries in "global" array. # Do the change: if 'cd' "${@-$HOME}" # call shell built-in. then # only if it succeeded. # See if new directory name (note, full name) is already known: while [ $dirat -lt $dirs ] do if [ "${DIRHIST[$dirat]}" = "$PWD" ] then break fi (( dirat=dirat + 1 )) done # Save new, or tell count for old: if [ $dirat -ge $dirs ] then DIRHIST[$dirat]="$PWD" DIRCOUNT[$dirat]=1 echo "(first time here)" else echo "(previous: ${DIRCOUNT[$dirat]})" (( DIRCOUNT[$dirat]=${DIRCOUNT[$dirat]} + 1 )) fi fi } # mycd(). # FUNCTION mcd(): DO A CD CHOOSING FROM A MENU: mcd() { set -- "${DIRHIST[@]}" # copy to positional parameters. set -s # sort them. (remove if not desired) select dir in "$@" # choose one. do if [ "${dir-}" ] # valid response. then echo "+ cd $dir" mycd "$dir" # use function for side-effects. else echo "cd: no change" fi break done } # mcd(). # FUNCTION lcd(): LIST CD HISTORY: lcd() { typeset -i dirat=0 # current saved dir index; local var. typeset -i dirs=${#DIRHIST[*]} # entries in "global" array. while [ $dirat -lt $dirs ] do echo "${DIRCOUNT[$dirat]}\t${DIRHIST[$dirat]}" (( dirat=dirat + 1 )) done | sort +0nr -1 } # lcd(). @EOF if test "`wc -lwc <ksh.cd`" != ' 114 444 2687' then echo ERROR: wc results of ksh.cd are `wc -lwc <ksh.cd` should be 114 444 2687 fi chmod 444 ksh.cd exit 0