【问题标题】:How can a ksh script determine the full path to itself, when sourced from another?当来自另一个脚本时,ksh 脚本如何确定其自身的完整路径?
【发布时间】:2011-11-28 19:29:43
【问题描述】:

当脚本是由 ksh 获取时,它如何确定它的路径?即

$ ksh ". foo.sh"

我在 BASH 中看到了非常好的方法,发布在 stackoverflow 和其他地方,但还没有找到 ksh 方法。

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

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

$ 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”。

【问题讨论】:

  • This page 似乎有一个可行的解决方案。
  • @Anson,我看到了,但如果我获取文件,它对我不起作用,只有当我运行脚本时。

标签: ksh


【解决方案1】:

如果是 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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      source 和 fork 之间的区别当然是 sourcing 导致调用的脚本在调用进程中执行。 Henk 在 ksh93 中展示了一个优雅的解决方案,但是如果像我一样,你被 ksh88 卡住了,那么你需要一个替代方案。我宁愿不使用 C-shell 语法更改默认的 ksh 采购方法,而且在工作中这将违反我们的编码标准,因此创建和使用 source() 函数对我来说是不可行的。 ps、$0 和 $_ 不可靠,所以这里有一个替代方案:

      $ 猫 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 变量都可以包含您的命令和参数,并且在采购和分叉的情况下都可以访问。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 好主意,但它没有按预期工作(至少对我来说)......我将我的示例代码添加到问题中,因为我无法在这里轻松发布代码。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-13
        • 2012-03-23
        • 2011-11-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-14
        相关资源
        最近更新 更多