【问题标题】:pushd/popd on ksh?在 ksh 上推送/弹出?
【发布时间】:2010-11-02 08:20:46
【问题描述】:

是否有等效于 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:

谢谢

【问题讨论】:

  • 一个出色的 pushd/popd 安装出现在 Oracle 的一个博客中 here - 可能与它在 Solaris 中的使用有关。

标签: bash ksh


【解决方案1】:

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

(cd tmp; echo "test" >tmpfile)

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • pushd 是在 $ROOTDIR/etc/dir.ksh 文件中定义的 shell 函数。
    • 不在我手边的任何 Solaris 服务器上。首先,我没有定义 $ROOTDIR,其次,/etc 中没有任何 *.ksh 文件。
    • 为了仔细检查,我检查了一个 Solaris 7 和一个 Solaris 10 框,所以我检查了多个版本。您的 dir.ksh 必须在本地定义,或者您可能没有使用 Solaris。在这种情况下,它是特定于操作系统的,而不是特定于机器的。
    • 正是 dir.ksh 也不在我的系统上
    • 如你所说,它可能是特定于操作系统的。
    【解决方案3】:

    当我发现 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
    }
    

    【讨论】:

    • 这似乎是最有希望的回应,我午饭后试试
    • 我希望它对你有用。我已经使用它十多年了。它并没有完全重现 csh/bash 中内置的 pushd/popd/dirs 的行为,但非常接近。
    • 非常好。我今天刚刚发现了这个,并将在我使用的 ksh 系统上将其设置为标准。 :)
    【解决方案4】:

    如果您可以只使用单级回溯,您可以将“cd -”或“cd $OLDPWD”别名为 popd。

    至于 dir.ksh...根据 Google,它是 commercial package 的一部分:

    注意

    popd 是定义的 KornShell 函数 在文件中

    $ROOTDIR/etc/dir.ksh.
    

    此文件通常由 处理过程中的登录shell 文件 $ROOTDIR/etc/profile.ksh。如果 您的系统无法识别 popd 命令,检查您的 profile.ksh 文件以确保调用 dir.ksh 包括在内。

    可用性

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

    【讨论】:

    • 我使用 cd - 但有时我需要更多 :)
    • dir.sh 这个名字足够通用,它可能无处不在。更重要的是,我认为 MKS 工具包已经不存在了。
    【解决方案5】:

    accepted answer 中有一个细微的错误。当没有 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
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-08
      • 2012-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 2019-05-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多