我可以在 KornShell 中获取当前脚本的绝对路径吗?

Posted

技术标签:

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

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

即如果我的脚本在/opt/scripts/myscript.ksh 中,我可以在该脚本中以编程方式发现/opt/scripts/myscript.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

$_ 变量返回“谁”

【讨论】:

以上是关于我可以在 KornShell 中获取当前脚本的绝对路径吗?的主要内容,如果未能解决你的问题,请参考以下文章

[Shell]获取当前正在执行脚本的绝对路径

调用shell脚本时,获取脚本的当前目录

Shell中获取当前脚本的绝对路径: $( cd “$( dirname “${BASH_SOURCE[0]}“ )“ && pwd)

在 Bash 和 KornShell (ksh) 中获取命令的退出代码

Bash 还是 KornShell (ksh)? [关闭]

shell脚本获取绝对目录