当源自另一个时,ksh脚本如何确定自身的完整路径?

时间:2011-09-30 21:58:29

标签: ksh

当脚本由ksh提供时,脚本如何确定它的路径?即。

$ ksh ". foo.sh"

我已经看到在BASH上发布的非常好的方法在stackoverflow和其他地方发布但尚未找到ksh方法。

使用“$ 0”不起作用。这只是指“ksh”。

更新:我尝试过使用“history”命令,但是不知道当前脚本之外的历史记录。

$ cat k.ksh
#!/bin/ksh
. j.ksh
$ cat j.ksh
#!/bin/ksh
a=$(history | tail -1)
echo $a
$ ./k.ksh
270 ./k.ksh

我希望它回显“* ./j.ksh”。

4 个答案:

答案 0 :(得分:5)

如果是AT& T ksh93,则此信息存储在变量.sh中的.sh.file命名空间中。

实施例

sourced.sh

(
 echo "Sourced: ${.sh.file}"
)

调用:

$ ksh -c '. ./sourced.sh'

结果:

Sourced: /var/tmp/sourced.sh

.sh.file变量与$0不同。虽然$0可以是ksh/usr/bin/ksh,或者当前正在运行的脚本的名称,.sh.file将始终引用文件作为当前范围。

在交互式shell中,此变量甚至不存在:

$ echo ${.sh.file:?}
-ksh: .sh.file: parameter not set

答案 1 :(得分:1)

我相信唯一可移植的解决方案是覆盖源命令:

source() {
  sourced=$1
  . "$1"
}

然后使用source而不是。 (脚本名称将在$ sourced中)。

答案 2 :(得分:1)

采购和分叉之间的差异在于,采购导致调用的脚本在调用过程中执行。 Henk在ksh93中展示了一个优雅的解决方案,但如果像我一样,你仍然坚持使用ksh88,那么你需要一个替代方案。我宁愿不使用C-shell语法更改源的默认ksh方法,并且在工作中它将违反我们的编码标准,因此创建和使用source()函数对我来说是行不通的。 ps,$ 0和$ _是不可靠的,所以这里有另一种选择:

$ cat b.sh;猫c.sh; ./b.sh

#!/bin/ksh
export SCRIPT=c.sh
. $SCRIPT 
echo "PPID: $$"
echo "FORKING c.sh"
./c.sh

如果我们在一个变量中设置被调用的脚本,并使用该变量来源它,那么该变量将可用于被调用的脚本,因为它们位于同一个进程空间中。

#!/bin/ksh
arguments=$_
pid=$$
echo "PID:$pid"
command=`ps -o args -p $pid | tail -1`
echo "COMMAND (from ps -o args of the PID): $command"
echo "COMMAND (from c.sh's \$_ ) : $arguments"
echo "\$SCRIPT variable: $SCRIPT"
echo dirname: `dirname $0`
echo ; echo

输出如下:

PID:21665
COMMAND (from ps -o args of the PID): /bin/ksh ./b.sh
COMMAND (from c.sh's $_ ) : SCRIPT=c.sh
$SCRIPT variable: c.sh
dirname: .


PPID: 21665
FORKING c.sh
PID:21669
COMMAND (from ps -o args of the PID): /bin/ksh ./c.sh
COMMAND (from c.sh's $_ ) : ./c.sh
$SCRIPT variable: c.sh
dirname: .

因此,当我们在调用者脚本中设置SCRIPT变量时,可以从源脚本的操作数访问该变量,或者,在分叉进程的情况下,将复制该变量以及父进程的所有其他环境变量为了孩子的过程。在任何一种情况下,SCRIPT变量都可以包含您的命令和参数,并且在源和分叉的情况下都可以访问。

答案 3 :(得分:0)

你应该在历史中找到它作为最后一个命令。