关于 which
which 是一项面向 Shell 的 Agent 技能,建议用 POSIX `command -v` 替代 `which` 来检查和解析命令。它说明可移植性差异、替换方法,以及需要显式处理路径的情况。
主要功能
- 01用 `command -v` 替代命令检查
- 02说明不同 Shell 的可移植性差异
- 03提供静默检查和错误提示方法
- 04区分命令名与文件路径
- 05介绍列出 `$PATH` 中可执行文件的方法
适用场景
- 01检查命令是否可用
- 02解析外部可执行文件路径
- 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 foo | command -v foo |
which foo >/dev/null 2>&1 | command -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 写法。