【问题标题】:Can I get the absolute path to the current script in KornShell?我可以在 KornShell 中获取当前脚本的绝对路径吗?
【发布时间】:2010-10-20 02:16:09
【问题描述】:

是否可以找到当前在 KornShell (ksh) 中执行的脚本的完整路径?

即如果我的脚本在/opt/scripts/myscript.ksh 中,我可以在该脚本中以编程方式发现/opt/scripts/myscript.ksh 吗?

谢谢,

【问题讨论】:

    标签: shell unix scripting path ksh


    【解决方案1】:

    脚本的调用方式存储在变量 $0 中。您可以使用readlink 获取绝对文件名:

    readlink -f "$0"
    

    【讨论】:

    • 感谢 0 美元小费,什么是 readlink?我的系统上似乎没有
    • 嗯,需要完全在 ksh 中的东西,没有依赖关系。不过谢谢
    • 恐怕这是不可能的 - 除非 ksh 有可能与文件系统进行交互,否则我不知道。你的操作系统是什么?
    • $0 指的是命令被调用时的名称,不需要引用文件系统对象。
    【解决方案2】:

    你可以使用:

    ## __SCRIPTNAME - name of the script without the path
    ##
    typeset -r __SCRIPTNAME="${0##*/}"
    
    ## __SCRIPTDIR - path of the script (as entered by the user!)
    ##
    __SCRIPTDIR="${0%/*}"
    
    ## __REAL_SCRIPTDIR - path of the script (real path, maybe a link)
    ##
    __REAL_SCRIPTDIR=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P )
    

    【讨论】:

    • 很好的答案 - 我希望如果您获取脚本,即'. /some/script.sh' 但它没有。
    • @synthesizerpatel:在 ksh93 中,${.sh.file} 也适用于源文件。
    • 正如 Gruik 所指出的,如果有指向 shell 脚本本身的符号链接,这将不起作用。因此,如果您将命令链接到 /usr/bin,那么 __REAL_SCRIPTDIR 将返回 /usr/bin,这(很可能)不是您想要的。您显然需要为此阅读链接
    【解决方案3】:

    这也有效,尽管如果它是一个链接,它不会给出“真实”的路径。它更简单,但不太精确。

    SCRIPT_PATH="$(whence ${0})"
    

    【讨论】:

      【解决方案4】:

      试试哪个命令。

      which scriptname
      

      将为您提供脚本的完整限定名及其绝对路径

      【讨论】:

        【解决方案5】:

        readlink -f 最好是可移植的,因为它会解析为目录和文件找到的每个链接。

        在 mac os x 上没有 readlink -f(可能通过 macports 除外),因此您只能使用 readlink 来获取特定符号链接文件的目标。

        $(cd -P ... pwd -P) 技术很好,但仅适用于解析指向脚本的目录的链接,如果脚本本身是符号链接,则它不起作用

        此外,还有一个没有提到的情况:当您通过将脚本作为参数传递给 shell (/bin/sh /path/to/myscript.sh) 来启动脚本时,$0 在这种情况下不可用

        我查看了 mysql “二进制文件”,其中许多实际上是 shell 脚本;现在我明白他们为什么要求--basedir 选项或需要从特定的工作目录启动;这是因为没有很好的解决方案来定位目标脚本

        【讨论】:

          【解决方案6】:

          试试这个:

          dir = $(dirname $0)
          

          【讨论】:

            【解决方案7】:

            这就是我所做的:

            if [[ $0 != "/"* ]]; then
              DIR=`pwd`/`dirname $0`
            else
              DIR=`dirname $0`
            fi
            

            【讨论】:

              【解决方案8】:

              变量 $RPATH 包含真实文件的相对路径或真实文件的真实路径。

              CURPATH=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P )
              
              CURLOC=$CURPATH/`basename $0`
              
              if [ `ls -dl $CURLOC |grep -c "^l" 2>/dev/null` -ne 0 ];then
              
                  ROFFSET=`ls -ld $CURLOC|cut -d ">" -f2 2>/dev/null`
              
                  RPATH=`ls -ld $CURLOC/$ROFFSET 2>/dev/null`
              
              else
              
                  RPATH=$CURLOC
              
              fi
              
              echo $RPATH
              

              【讨论】:

              • 这似乎是处理脚本本身的符号链接情况的唯一可用方法,虽然它很可怕。
              【解决方案9】:

              好吧,我花了一段时间,但这个太简单了,它会尖叫。

              _SCRIPTDIR=$(cd $(dirname $0);echo $PWD)
              

              由于 CD 在生成的 shell 中使用 $() 运行,因此不会影响当前脚本。

              【讨论】:

                【解决方案10】:

                在 korn shell 中,如果您在相关脚本中进行采购,所有这些 $0 解决方案都会失败。得到你想要的东西的正确方法是使用 $_

                $ cat bar
                
                echo dollar under is $_
                echo dollar zero is $0
                
                $ ./bar
                
                dollar under is ./bar
                dollar zero is ./bar
                
                $ . ./bar
                dollar under is bar
                dollar zero is -ksh
                

                注意到最后一行了吗?使用 $_。至少在科恩。 bash、csh 等中的 YMMV。

                【讨论】:

                • 这个答案应该被纳入接受的答案。我挣扎了半个小时来寻找我的 ksh 脚本,直到我意识到我需要 $_
                【解决方案11】:

                我升级了 Edward Staudt 的答案,以便能够处理绝对路径符号链接,以及链接链。

                DZERO=$0
                while true; do
                  echo "Trying to find real dir for script $DZERO"
                  CPATH=$( cd -P -- "$(dirname -- "$(command -v -- "$DZERO")")" && pwd -P )
                  CFILE=$CPATH/`basename $DZERO`
                  if [ `ls -dl $CFILE | grep -c "^l" 2>/dev/null` -eq 0 ];then
                    break
                  fi
                  LNKTO=`ls -ld $CFILE | cut -d ">" -f2 | tr -d " " 2>/dev/null`
                  DZERO=`cd $CPATH ; command -v $LNKTO`
                done
                

                丑陋,但有效...... 运行后,路径为$CPATH,文件为$CFILE

                【讨论】:

                  【解决方案12】:

                  使用 $_ 提供最后一条命令。

                  >source my_script
                  

                  如果我发出两次命令,则有效:

                  >source my_script
                  >source my_script
                  

                  如果我使用不同的命令序列:

                  >who
                  >source my_script
                  

                  $_ 变量返回“谁”

                  【讨论】:

                    猜你喜欢
                    • 2018-04-13
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-08-26
                    • 2012-01-21
                    • 2013-06-26
                    • 2010-09-22
                    • 2011-06-06
                    • 2012-05-10
                    相关资源
                    最近更新 更多