Path: uunet!seismo!sundc!pitstop!sun!amdcad!ames!ll-xn!husc6!spdcc!m2c!necntc!ncoast!allbery
From: gwyn@brl-smoke.ARPA (Doug Gwyn )
Newsgroups: comp.sources.misc
Subject: Re: directory stack manipulation routines for bourne shell
Keywords: pushd, popd, dirs ...
Message-ID: <4766@ncoast.UUCP>
Date: 29 Sep 87 20:27:07 GMT
Sender: allbery@ncoast.UUCP
Organization: Ballistic Research Lab (BRL), APG, MD.
Lines: 93
Approved: allbery@ncoast.UUCP
X-Archive: comp.sources.misc/8709/16

In article <4563@ncoast.UUCP> rickers@RUTGERS.EDU@drexel.UUCP (Rick Wargo) writes:
>        Having been  working  for  a  long  time  under  csh  and  being
>accustomed  to  the commands pushd and popd, I was saddened to find that
>these commands were not avaiable under  my  version  of  Microport  Unix
>System  V (version 2.2).

Sure they are!  But you need to set them up yourself as shell functions.
I use something like the following (actually mine is much more elaborate,
supporting "myx" layer banners etc., and exploits our sh's "builtin"
command to allow redefining "cd" as a function):

DIRSTACK=...	# for pushd, popd, swapd
PREVDIR="$HOME"	# for backd

if [ -z "$HOST" ]
then	HOST=`uname` export HOST
fi

backd(){ ch "$PREVDIR"; echo `pwd`; }

# Following should be "cd", but you need "builtin" for that.
ch(){
	PREVDIR="$CWD"
	if [ $# -lt 1 ]
	then	cd
	else	cd "$1"
	fi
	CWD=`pwd` export CWD
	# exported so interactive subshells can ch $CWD to outwit symbolic links
	if [ "$CWD" = "$HOME" ]
	then	PS1="$HOST"
	else	PS1="$HOST":`echo "$CWD" | sed -e "s!^$HOME!~!"`
	fi
	PS1="$PS1"'$ '
}

dirs(){
	if [ "$DIRSTACK" != "" ]
	then
		echo "$CWD $DIRSTACK"
	fi
}

popd(){
	set $DIRSTACK
	if [ $# -ge 2 ]
	then	DIRSTACK="$*"
		ch $1
		set $DIRSTACK	# ch clobbered $*
		shift
		DIRSTACK="$*"
	fi
	set --
}

pushd(){
	DIRSTACK=$CWD" $DIRSTACK"
	if [ $# -lt 1 ]
	then	set $HOME
	fi
	if ch $1
	then	echo $DIRSTACK
	else	popd
	fi
	set --
}

swapd(){
	DIRSTACK=$CWD" $DIRSTACK"
	set $DIRSTACK
	if [ $# -ge 3 ]
	then	DIRSTACK="$*"
		ch $2
		set $DIRSTACK	# ch clobbered $*
		DIRSTACK="$1"
		shift 2
		DIRSTACK=$DIRSTACK" $*"
		echo $DIRSTACK
	else	shift
		DIRSTACK="$*"
		echo 'swapd: No previous directory' >&2
		set --
		return 1
	fi
	set --
}

readonly backd ch dirs popd pushd swapd

if [ "$CWD" ]
then	ch "$CWD"	# outwit symbolic links
else	ch "`pwd`"
fi
