使用 shell 脚本覆盖原始命令时查找原始命令的路径?

使用 shell 脚本覆盖原始命令时查找原始命令的路径?

我正在编写一个包装脚本来包装另一个命令的执行;在本例中为 Chefkitchen命令。我的脚本也将被调用kitchen并提前放入,$PATH以便kitchen从 bash 运行将运行我的包装器脚本。

问题是:如何调用原始版本kitchen?当然,最明显的方法就是给出完整路径 - 只需放入/usr/bin/kitchen脚本中,但其他人可能会将其安装在不同的路径中。当然,这排除了任何其他包装器脚本 - 如果解决方案是可堆叠的,那就太好了。

我想到了两种方法,两种方法都针对同一主题:

  1. 在脚本中,通过$PATH.将每个条目与$(dirname "$0")使用stat设备号和索引节点号进行比较,看看是否是同一个目录。如果是这样,请将其从 中删除$PATH。然后就可以调用kitchen,因为它不应该重新调用包装器脚本。
  2. 与 #1 类似,但$PATH在脚本中手动查找,并stat在每个结果上使用与$0.继续跳过,直到找到自己,然后使用找到的下一个。如果我们从未找到自己,那么只需正常执行它(以处理包装器不在其中$PATH但通过提供其路径来执行的情况)

有没有更好的办法?或者典型的 Debian 或 Ubuntu Linux 系统上是否已经存在执行此操作的代码?

答案1

我过去曾做过几次类似的事情,我要做的只是command kitchen在脚本中使用,将其命名为其他名称my-kitchen,然后创建一个别名:

alias kitchen=/path/to/my-kitchen

但不确定这是否适合您的用例。

答案2

您可以使用反斜杠转义别名,以防止它被 shell 扩展。 command也有效。

kitchen我的桌面上没有,所以我将通过别名pwd来演示uname -r

$ alias pwd='uname -r'
$ pwd
5.10.0-8-amd64
$ \pwd
/home/cas
$ command pwd
/home/cas
$ unalias pwd
$ pwd
/home/cas

答案3

听起来您想执行kitchen中的下一个$PATH

#!/bin/bash
me="$0" 
foundit=""
for d in $( echo "$PATH" | tr ":" " " ) ; do
  if [[ $foundit  == "" ]] ; then
    if [[ "$me" != "$d/kitchen" ]] ; then
      if [[ -x "$d/kitchen" ]] ; then
        foundit="$d/kitchen" 
      fi
    fi
  fi
done
# the next "kitchen" is in "`$foundit`"
# read `man bash`, about the `eval` and `exec` builtins

相关内容