bash 在 ksh 上推送/弹出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/984635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
pushd/popd on ksh?
提问by hhafez
Is there an equivalent of the bash pushd/popd build in commands for the KSH?
是否有相当于 KSH 的 bash pushd/popd 内置命令?
For those who don't know what pushd and popd in bash do, here is the description from the man page
对于那些不知道 bash 中 pushd 和 popd 做什么的人,这里是手册页的描述
pushd [-n] [dir]
pushd [-n] [+n] [-n]
Adds a directory to the top of the directory stack, or rotates
the stack, making the new top of the stack the current working
directory. With no arguments, exchanges the top two directo-
ries and returns 0, unless the directory stack is empty.
popd [-n] [+n] [-n]
Removes entries from the directory stack. With no arguments,
removes the top directory from the stack, and performs a cd to
the new top directory. Arguments, if supplied, have the fol-
lowing meanings:
Thanks
谢谢
回答by Eddie
When I discovered that ksh didn't include these, I wrote my own. I put this in ~/bin/dirstack.kshand my .kshrcfile includes it like this:
当我发现 ksh 不包含这些时,我自己写了。我把它放进去~/bin/dirstack.ksh,我的.kshrc文件像这样包含它:
. ~/bin/dirstack.ksh
Here are the contents of dirstack.ksh:
以下是内容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 [ ] ; then
if [ ${1#\+[0-9]*} ] ; then
# ======= "pushd dir" =======
# is "dir" reachable?
if [ `(cd ) 2>/dev/null; echo $?` -ne 0 ] ; then
cd # 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
# 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
}
回答by beggs
If you are OK with just a single level of back tracking you can alias 'cd -' or 'cd $OLDPWD' to popd.
如果您只需要一级回溯就可以了,您可以将“cd -”或“cd $OLDPWD”别名为 popd。
As for dir.ksh... according to Google it's part of a commercial package:
至于 dir.ksh ......据谷歌称,它是商业包的一部分:
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
笔记
popd 是文件中定义的 KornShell 函数
$ROOTDIR/etc/dir.ksh.在处理文件 $ROOTDIR/etc/profile.ksh 期间,该文件通常由登录 shell 处理。如果您的系统无法识别 popd 命令,请检查您的 profile.ksh 文件以确保包含对 dir.ksh 的调用。
可用性
MKS 高级用户工具包 MKS 系统管理员工具包 MKS 开发人员工具包 MKS 互操作性工具包 MKS 专业开发人员工具包 MKS 企业开发人员工具包 MKS 企业开发人员工具包 64 位版
回答by Greg Hewgill
I usually use a subshell for this sort of thing:
我通常使用子shell来处理这种事情:
(cd tmp; echo "test" >tmpfile)
This changes to the tmpdirectory and creates a file called tmpfilein 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.
这会更改tmp目录并创建一个tmpfile在该目录中调用的文件。子shell返回后,当前目录恢复到子shell启动前的目录。这是因为每个 shell 实例对“当前目录”是什么都有自己的想法,并且在子 shell 中更改当前目录不会影响调用它的 shell。
回答by ccy
There's a subtle bug in the accepted answer. When 'pushd' is invoked with no arg ($1 = "") AND an empty dir_stack, it injects a blank entry into said stack that can't be "popped" out of. Catching the edge case seems to fix it.
接受的答案中有一个微妙的错误。当在没有参数($1 = "")和空的 dir_stack 的情况下调用 'pushd' 时,它会向所述堆栈中注入一个无法“弹出”的空白条目。抓住边缘情况似乎可以解决这个问题。
Here's the corrected code. EDIT: complain to stderr when nowhere to push (consistent w/bash pushd). Left the indexed listing on 'dirs' as I feel it's an improvement :')
这是更正后的代码。编辑:在无处推送时向 stderr 抱怨(与 bash pushd 保持一致)。将索引列表留在“目录”上,因为我觉得这是一个改进:')
# 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 [ ] ; then
if [ ${1#\+[0-9]*} ] ; then
# ======= "pushd dir" =======
# is "dir" reachable?
if [ `(cd ) 2>/dev/null; echo $?` -ne 0 ] ; then
cd # 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
# 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" =======
# swap only if there's a value to swap with
if [ ${#dir_stack[*]} = "0" ]; then
echo "ksh: pushd: no other directory" >&2
else
cd ${dir_stack[sd]} # Swap stack top with +1 position
dir_stack[sd]=$OLDPWD
fi
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
}
回答by Suvesh Pratapa
If your system fails to recognize the pushd command, check your profile.ksh file to ensure that a call to dir.ksh is included.
如果您的系统无法识别 pushd 命令,请检查您的 profile.ksh 文件以确保包含对 dir.ksh 的调用。

