pushd/popd on ksh?
When I discovered that ksh didn't include these, I wrote my own. I put this in ~/bin/dirstack.ksh
and my .kshrc
file includes it like this:
. ~/bin/dirstack.ksh
Here are the contents of dirstack.ksh
:
# Implement a csh-like directory stack in ksh
#
# environment variable dir_stack contains all directory entries except
# the current directory
unset dir_stack
export dir_stack
# Three forms of the pushd command:
# pushd - swap the top two stack entries
# pushd +3 - swap top stack entry and entry 3 from top
# pushd newdir - cd to newdir, creating new stack entry
function pushd
{
sd=${#dir_stack[*]} # get total stack depth
if [ $1 ] ; then
if [ ${1#\+[0-9]*} ] ; then
# ======= "pushd dir" =======
# is "dir" reachable?
if [ `(cd $1) 2>/dev/null; echo $?` -ne 0 ] ; then
cd $1 # get the actual shell error message
return 1 # return complaint status
fi
# yes, we can reach the new directory; continue
(( sd = sd + 1 )) # stack gets one deeper
dir_stack[sd]=$PWD
cd $1
# check for duplicate stack entries
# current "top of stack" = ids; compare ids+dsdel to $PWD
# either "ids" or "dsdel" must increment with each loop
#
(( ids = 1 )) # loop from bottom of stack up
(( dsdel = 0 )) # no deleted entries yet
while [ ids+dsdel -le sd ] ; do
if [ "${dir_stack[ids+dsdel]}" = "$PWD" ] ; then
(( dsdel = dsdel + 1 )) # logically remove duplicate
else
if [ dsdel -gt 0 ] ; then # copy down
dir_stack[ids]="${dir_stack[ids+dsdel]}"
fi
(( ids = ids + 1 ))
fi
done
# delete any junk left at stack top (after deleting dups)
while [ ids -le sd ] ; do
unset dir_stack[ids]
(( ids = ids + 1 ))
done
unset ids
unset dsdel
else
# ======= "pushd +n" =======
(( sd = sd + 1 - ${1#\+} )) # Go 'n - 1' down from the stack top
if [ sd -lt 1 ] ; then (( sd = 1 )) ; fi
cd ${dir_stack[sd]} # Swap stack top with +n position
dir_stack[sd]=$OLDPWD
fi
else
# ======= "pushd" =======
cd ${dir_stack[sd]} # Swap stack top with +1 position
dir_stack[sd]=$OLDPWD
fi
}
function popd
{
sd=${#dir_stack[*]}
if [ $sd -gt 0 ] ; then
cd ${dir_stack[sd]}
unset dir_stack[sd]
else
cd ~
fi
}
function dirs
{
echo "0: $PWD"
sd=${#dir_stack[*]}
(( ind = 1 ))
while [ $sd -gt 0 ]
do
echo "$ind: ${dir_stack[sd]}"
(( sd = sd - 1 ))
(( ind = ind + 1 ))
done
}
If you are OK with just a single level of back tracking you can alias 'cd -' or 'cd $OLDPWD' to popd.
As for dir.ksh... according to Google it's part of a commercial package:
NOTE
popd is a KornShell function defined in the file
$ROOTDIR/etc/dir.ksh.
This file is normally processed by a login shell during the processing of the file $ROOTDIR/etc/profile.ksh. If your system fails to recognize the popd command, check your profile.ksh file to ensure that a call to dir.ksh is included.
AVAILABILITY
MKS Toolkit for Power Users MKS Toolkit for System Administrators MKS Toolkit for Developers MKS Toolkit for Interoperability MKS Toolkit for Professional Developers MKS Toolkit for Enterprise Developers MKS Toolkit for Enterprise Developers 64-Bit Edition
I usually use a subshell for this sort of thing:
(cd tmp; echo "test" >tmpfile)
This changes to the tmp
directory and creates a file called tmpfile
in that directory. After the subshell returns, the current directory is restored to what it was before the subshell started. This is because each shell instance has its own idea of what the "current directory" is, and changing the current directory in a subshell does not affect the shell that called it.