mcpField
W
which

which

github.com/petr-korobeinikov开发171 次安装3 天前更新
代码仓库

关于 which

which 是一项面向 Shell 的 Agent 技能,建议用 POSIX `command -v` 替代 `which` 来检查和解析命令。它说明可移植性差异、替换方法,以及需要显式处理路径的情况。

主要功能

  1. 01用 `command -v` 替代命令检查
  2. 02说明不同 Shell 的可移植性差异
  3. 03提供静默检查和错误提示方法
  4. 04区分命令名与文件路径
  5. 05介绍列出 `$PATH` 中可执行文件的方法

适用场景

  1. 01检查命令是否可用
  2. 02解析外部可执行文件路径
  3. 03审查 Shell 代码和构建说明

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/petr-korobeinikov/skills --skill which

安装后在 Claude Code 中输入/which确认已加载。

详细介绍

which

切勿使用 which 检查命令是否存在或打印其路径。 请改用 command -v。

原因

  • command -v 是 POSIX 标准规定的 shell 内置命令 (bash、zsh、dash、ash、ksh、busybox sh)。 which 是外部程序, 可能不存在、 被设为别名, 或被 shell 函数替代。
  • which 的行为因实现而异: BSD、GNU、Debian 的 shell 脚本版 which、zsh 的内置命令 和 busybox 的 applet 在标志、 输出格式 和退出码上都不相同。
  • command -v 会报告 shell 内置命令、 函数 和别名—— 而不仅是 $PATH 中的文件—— 这通常才是调用方真正想要的结果。
  • 找不到名称时,command -v 会返回可靠的非零退出码, 且不会向标准输出或标准错误输出任何内容。

直接替换

不要请用
which foocommand -v foo
which foo >/dev/null 2>&1command -v foo >/dev/null
if which foo; then …if command -v foo >/dev/null; then …

去掉 2>&1 是因为找不到名称时, command -v 不会向标准错误输出任何内容。

以下两种情况无法用单行命令替换,需要使用下面的惯用写法:

  • path=$(which foo) — command -v 可能返回内置命令名称或别名字符串, 而不是文件系统路径。
  • which -a foo — command -v 只解析第一个匹配项。

惯用写法

静默检查是否存在:

if command -v foo >/dev/null; then
  # ...
fi

检查是否存在,并显示清晰的失败消息:

command -v foo >/dev/null || {
  echo "foo is required but not installed" >&2
  exit 1
}

解析文件系统路径:

foo_path=$(command -v foo) || {
  echo "foo not found" >&2
  exit 1
}
case "$foo_path" in
  /*) ;;
  *)  echo "foo is not an external binary (got: $foo_path)" >&2
      exit 1 ;;
esac

command -v 可能会输出:

  • /usr/bin/foo — $PATH 中的外部文件;
  • foo — shell 内置命令或函数;
  • alias foo='…' — 别名。

/* 保护条件只接受第一种形式。

边缘情况

  • 列出 $PATH 中的所有匹配项(which -a) 没有单次调用的 POSIX 等效写法。 请显式遍历 $PATH:

    ( IFS=:
      for dir in $PATH; do
        candidate=${dir:-.}/foo
        [ -f "$candidate" ] && [ -x "$candidate" ] && printf '%s\n' "$candidate"
      done )
    

    [ -f ] 与 [ -x ] 结合使用,只会筛选普通可执行文件—— 这与 which -a 报告的内容一致; 单独使用 [ -x ] 也会接受带有执行位的目录。

    在 bash 和 zsh 中,type -a foo 更简短, 但不具备可移植性。

  • Makefile。 配方通过 $(SHELL) 运行, 默认值为 /bin/sh。 如果项目将 SHELL 设为非 POSIX shell, 请先将配方指定为 POSIX shell—— 例如 SHELL := /bin/sh—— 然后再使用 command -v。

适用范围

此规则适用于任何以 POSIX shell 编写或运行的内容: Bash 工具调用、 SKILL.md / README.md 中的代码片段、 scripts/ 下的脚本、 Makefile、 CI 配置、 Dockerfile、 安装说明、 建议使用的单行命令。

不适用范围: fish, 以及内部封装了 which 的工具 (CMake 的 find_program、npm bin 等)。

如果编辑文件时遇到 which 调用, 请在同一次编辑中将其替换为等效的 command -v 写法。

评论

支持 Markdown