Functions for C-shell style directory stack in Korn shell
Ray Lubinsky
rwl at uvacs.CS.VIRGINIA.EDU
Sun Jul 10 06:10:33 AEST 1988
I promised to post these a while ago and the recent set of postings about ksh
functions reminded me.
My apologies; this is a fairly large posting, but I do get tired of people
going on about how ksh is not quite able to match some of the C-shell's tricks.
Analogs to C-shell's "pushd", "popd", and "dirs" functions are included plus
the function "roll" which is easier than "pushd +count" for rolling the
directory stack (though that too is implemented). "Cd" is aliased to the
function "chdir" which handles the directory stack and prints it out after
changing directory. Naturally, you can modify "chdir" so that it also
does an ls(1), prints the date, or plays rogue every time you change
directories.
Enjoy! Feel free to point out bugs &c.
-------------------------------- CUT HERE ------------------------------------
#
# Directory stack support for ksh.
#
# Author: Ray Lubinsky, rwl at uvacs.cs.virginia.edu
# Site: Computer Science Department, University of Virginia
#
# This file contains functions and aliases which implement a
# directory stack for the Korn shell very similar to that built
# into the C-shell.
#
alias cd='chdir' # THIS IS NOT OPTIONAL
alias pop='popd' # optional
alias push='pushd' # optional
#
# pushd -- push directory stack
#
# Usage: pushd [<directory> | +<position>]
#
# You may either change directories by pushing a new directory or
# by reordering the directory stack. The directory on the top of
# the stack (first token in the $DIRSTACK variable) becomes the
# current working directory. Giving no arguments is the same as
# "pushd +1"; see function roll() defined below.
#
function pushd
{
if [ $# -gt 1 ] ; then
echo 'pushd: Too many arguments.'
return 1
fi
integer OK=1 FLIP=0 POS=0
case $1 in
'') FLIP=1 ;;
+*) POS=${1#+}
if [ 0 -eq $POS -o $POS -ne "$POS" ] ; then
echo 'pushd: Bad directory.'
return 1
fi ;;
*) typeset +x NEWDIR=$1
esac
set -- ${DIRSTACK:=$PWD}
if [ $FLIP -ne 0 ] ; then
if [ $# -lt 2 ] ; then
echo 'pushd: No other directory.'
return 1
else
typeset +x SECOND=$1 FIRST=$2
shift 2
set -- $FIRST $SECOND $*
fi
elif [ $POS -eq 0 ] ; then
set -- $NEWDIR $DIRSTACK
elif [ $POS -ge $# ] ; then
echo 'pushd: Directory stack not that deep.'
return 1
else
typeset +x STACK=''
integer i=0
while [ $i -lt $POS ]
do
STACK="$STACK $1"
shift
let i=i+1
done
set -- $* $STACK
fi
'cd' $1 1>/dev/null
OK=$?
shift
if [ $OK -eq 0 ] ; then
DIRSTACK="$PWD $*"
dirs
else
shift
DIRSTACK=$*
fi
return $OK
}
#
# popd -- pop directory stack
#
# Usage: popd [+<position>]
#
# Pop a directory off the directory stack. With no arguments this
# pops the top (current working) directory and changes directory to
# the new top-of-stack directory. With the position argument, the
# directory at the given ordinal position from the top of the stack
# is removed from $DIRSTACK; this never results in a change of current
# working directory.
#
function popd
{
if [ $# -gt 1 ] ; then
echo 'popd: Too many arguments.'
return 1
fi
integer OK=0 POS=0
case $1 in
'') OK=1 ;;
+*) POS=${1#+}
if [ 0 -lt $POS -a $POS -eq "$POS" ] ; then
OK=1
fi
esac
if [ $OK -eq 0 ] ; then
echo 'popd: Bad directory.'
return 1
fi
set -- $DIRSTACK
if [ $# -le 1 ] ; then
echo 'popd: Directory stack empty.'
return 1
elif [ $POS -eq 0 ] ; then
shift
elif [ $POS -ge $# ] ; then
echo 'popd: Directory stack not that deep.'
return 1
else
typeset +x STACK=''
integer i=0
while [ $i -ne $POS ]
do
STACK="$STACK $1"
shift
let i=i+1
done
shift
set -- $STACK $*
fi
'cd' $1 1>/dev/null
OK=$?
if [ $OK -eq 0 ] ; then
DIRSTACK=$*
dirs
fi
return $OK
}
#
# chdir -- wrapper function for cd which adjusts DIRSTACK
#
# Usage: chdir [<directory>]
#
# This function is used as the change-directory function. To have cd
# work right, you must alias cd to chdir. Note that instances of cd
# in this function are quoted so that you get the real builtin rather
# than the alias.
#
function chdir
{
typeset +x DIR
case $# in
0) DIR=$HOME ;;
1) DIR=$1 ;;
2) DIR=`echo $PWD | /bin/sed "s$1$2"` ;;
*) echo 'cd: too many arguments' ; return 1
esac
if 'cd' $DIR 1>/dev/null ; then
set -- $DIRSTACK
DIRSTACK=$PWD
if [ $# -gt 1 ] ; then
shift
DIRSTACK="$DIRSTACK $*"
fi
dirs
else
return 1
fi
}
#
# roll -- roll directory stack
#
# Usage: roll [<count>]
#
# I use this function when I want to roll the directory stack rather
# than using "pushd +<count>" to avoid typing extra characters.
# With no arguments, the function is equivalent to "pushd +1".
#
function roll
{
typeset +x ROLL
case $# in
0) ROLL=1 ;;
1) case $1 in
[0-9]*) ROLL=$1 ;;
*) echo 'roll: number expected' ; return 1
esac ;;
*) echo 'roll: too many arguments' ; return 1 ;;
esac
pushd +$ROLL
}
#
# dirs -- print directory stack
#
# Usage: dirs
#
# Like the C-shell builtin, this prints the directory stack.
#
function dirs
{
if [ "$HOME" = '/' ] ; then
echo ${DIRSTACK:=$PWD}
else
echo ${DIRSTACK:=$PWD} | /bin/sed "s$HOME~g"
fi
}
-------------------------------- CUT HERE ------------------------------------
--
| Ray Lubinsky, UUCP: ...!uunet!virginia!uvacs!rwl |
| Department of BITNET: rwl8y at virginia |
| Computer Science, CSNET: rwl at cs.virginia.edu -OR- |
| University of Virginia rwl%uvacs at uvaarpa.virginia.edu |
More information about the Comp.unix.questions
mailing list