编辑2:

编辑2:

我和其他脚本使用了一个可执行文件/usr/bin/foo,但它的行为有点不正常,因此我制作了一个具有相同文件名的 Bash 包装器,并在/usr/local/bin/foo其中修复了其错误行为。我PATH的是/usr/local/bin:/usr/bin。在包装器脚本中,我必须通过绝对路径运行原始可执行文件,以免进入无限循环:

$ cat /usr/local/bin/foo
#/bin/zsh
/usr/bin/foo | grep -v "^INFO" # reduce output

是否有任何(也许是 Zsh 或 Bash 特定的)简单的方法来执行 next fooin PATH,即在执行current 的目录之后的目录foo中,这样我就不必使用原始可执行文件的绝对路径?PATHfoo

我可以为它创建一个函数/etc/zshenv,这没什么大不了的。我只是想知道是否有什么标准。我不想使用别名或修复原始可执行文件。


编辑1:= $ cat /usr/local/bin/foo #/bin/zsh path=(${path/#%$0:A:h}) foo | grep -v "^INFO" # 减少输出

这应该清空(但保留) PATH ( ) 中与当前可执行文件 ( ) 的绝对 ( ) 目录 ( )${path/...}完全匹配 ( ) 的所有字符串。老实说,我从 StackExchange 组装了它,但并不完全理解它。我希望它不会咬我。#%:A:h$0

编辑2:

$ cat /usr/local/bin/foo
#/bin/zsh
path[${path[(i)$0:A:h]}]=() foo | grep -v "^INFO" # reduce output

$path[(i)foo]foo查找数组中的索引path或 1 加数组长度。

答案1

您可以找出脚本所在的目录($0:h在 zsh 中,"${0%/*}"在 sh 中)并从中删除该目录PATHpath=(${path:#$0:h})在 zsh 中,sh 中更复杂。如果PATH两次包含相同的目录(例如通过符号链接),则此操作可能会失败。

直接方法的缺点是,这会从路径中删除目录,但同一目录中的其他程序可能是理想的。您可以通过仅使用修改后的路径进行路径查找来解决此问题。

next=$(path=(${path:#$0:h}); print -lr -- =$0:t)
$next

相反,我会PATH手动进行查找并跳过正在运行的脚本的任何出现。

for d in $path; do
  if [[ -x $d/$0:t && ! $d/$0:t -ef $0 ]]; then
    exec $d/$0:t
  fi
done

答案2

示例:
对我来说type -a egrep,打印用户定义的别名和实际egrep命令,在我的 $HOME/bin/ 中添加另一个命令egrep也会显示它......按顺序;首先是别名,然后是与 PATH 具有相同顺序的其余项目。

$ cd # 回家

$ mkdir -p bin

$ PATH=$HOME/bin:$PATH

$ 类型 -a egrep
egrep 的别名为 `egrep --color=auto'
egrep 是 /bin/egrep

$ echo -e >bin/egrep '#!/bin/bash\necho TEST'

$ chmod 755 bin/egrep

$ 类型 -a egrep
egrep 的别名为 `egrep --color=auto'
egrep 是 /home/$USER/bin/egrep
egrep 是 /bin/egrep

# 假设你确定它是唯一不在 /home 中且不是别名的
$ 类型 -a egrep | grep -Ev '/home|别名' |切-d''-f3
/bin/egrep

$ rm $HOME/bin/egrep

答案3

你可以这样做:

#! /bin/zsh -

# find the other occurrences of a command with the same name in $path that
# are a different file
other_mes=(
  ${^path/#%/.}/$0:t(N*^e['[[ $REPLY -ef $0 ]]'])
)

if (( ! $#other_mes )) {
  print -ru2 Could not find any other $0:t in PATH.
  exit 1
}

# run the first found
$other_mes[1] "$@" | grep -v '^INFO'

# return the exit status of the other me, not of grep
exit $pipestatus[1]
  • ${path/#%/.}$path将的空元素替换为.
  • $0:t: 的尾部(基本名称)$0
  • [[ a -ef b ]]a如果在符号链接解析后发现和b是同一个文件,则返回 true ,因为它们是同一文件的 2 个路径(如/usr/bin/foovs/bin/foo因为/bin恰好是/usr/binor的符号链接../bin/foo并且$PWD/usr/localor /usr/foo/../bin/foo,或者它们是彼此的硬链接或符号链接)。

使用sh语法(以及大多数[支持的实现),并假设不以换行符结尾,可能是:-ef$0

#! /bin/sh -
other_me=$(
  me=$(dirname -- "$0")
  IFS=:; set -o noglob
  for dir in $PATH''; do
    other_me=${dir:-.}/$me
    if [ -x "$other_me" ] && [ -f "$other_me" ] && [ ! "$other_me" -ef "$me" ]; then
      printf '%s\n' "$other_me"
      exit
    fi
  done
  printf>&2 '%s\n' "Cound not find any other $me in PATH."
  exit 1
) || exit

{
  exit_status=$(
    {
      {
        "$other_me" "$@" 4>&-
        echo "$?" >&4 4>&-
      } 3>&- | grep -v '^INFO' >&3 3>&- 4>&-
    } 4>&1
  )
} 3>&1
exit "$exit_status"

通过末尾的复杂位来获取 的退出状态$other_me

相关内容