8

是否有等效于 KSH 的 bash pushd/popd 内置命令?

对于那些不知道 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:

谢谢

4

5 回答 5

10

当我发现 ksh 不包含这些时,我编写了自己的。我把它放进去~/bin/dirstack.ksh,我的.kshrc文件包括这样的:

. ~/bin/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 [ $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
}
于 2009-06-12T01:44:39.767 回答
4

如果您对单级回溯没问题,您可以将“cd -”或“cd $OLDPWD”别名为 popd。

至于 dir.ksh ......根据谷歌,它是商业包的一部分:

笔记

popd 是文件中定义的 KornShell 函数

$ROOTDIR/etc/dir.ksh.

在处理文件 $ROOTDIR/etc/profile.ksh 期间,该文件通常由登录 shell 处理。如果您的系统无法识别 popd 命令,请检查您的 profile.ksh 文件以确保包含对 dir.ksh 的调用。

可用性

面向高级用户的 MKS 工具包 面向系统管理员的 MKS 工具包 面向开发人员的 MKS 工具包 面向互操作性的 MKS 工具包 面向专业开发人员的 MKS 工具包 面向企业开发人员的 MKS 工具包 面向企业开发人员的 MKS 工具包 64 位版

于 2009-06-12T02:41:03.000 回答
2

我通常使用 subshel​​l 来处理这类事情:

(cd tmp; echo "test" >tmpfile)

这将更改tmp目录并创建一个tmpfile在该目录中调用的文件。子shell返回后,当前目录恢复到子shell启动前的状态。这是因为每个 shell 实例对“当前目录”是什么都有自己的想法,并且在子 shell 中更改当前目录不会影响调用它的 shell。

于 2009-06-12T01:38:33.353 回答
1

接受的答案中有一个微妙的错误。当没有 arg ($1 = "") 和一个空的 dir_stack 调用 'pushd' 时,它会在所述堆栈中注入一个无法“弹出”出来的空白条目。抓住边缘情况似乎可以解决它。

这是更正后的代码。编辑:当无处可推时向 stderr 抱怨(与 bash pushd 一致)。将索引列表留在“dirs”上,因为我觉得这是一个改进:')

# 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" =======
      # 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
}
于 2019-07-13T18:03:06.497 回答
0

如果您的系统无法识别 pushd 命令,请检查您的 profile.ksh 文件以确保包含对 dir.ksh 的调用。

于 2009-06-12T01:40:44.237 回答