跳转到内容

which

which 用于在 $PATH 里查找可执行文件的位置,回答「我敲下这个命令,实际跑起来的是哪个文件」。

Terminal window
which [选项] 命令名...

按 $PATH 里的目录顺序查找,第一个命中的就是实际会被执行的那个 找不到时没有输出,返回非零

shell 解析一个命令名的顺序是:别名 → 函数 → 内建命令 → $PATH 里的可执行文件。which 只看最后一层,前三层它一概不知道。

所以 which cd 什么都查不到 —— cd 是 shell 内建命令,磁盘上根本没有这个文件,见 cd。同理,自己定义的别名和函数 which 也看不见。

要知道 shell 究竟会执行什么,用 type:

Terminal window
type -a ls

输出:

ls is aliased to `ls --color=auto'
ls is /usr/bin/ls
选项 说明
-a 列出 $PATH 里所有同名的可执行文件,不止第一个
--skip-dot 跳过 $PATH 里以 . 开头的目录
--skip-tilde 跳过用户家目录下的路径
--read-alias 读取别名(需要 shell 把别名传进来,多数发行版默认不生效)

which 有好几个不同的实现(debianutils、GNU、以及 shell 内建版),选项支持并不一致 只有 -a 是各家都有的

1. 查命令的位置

Terminal window
which python3
which -a python3

输出:

/usr/bin/python3
/usr/local/bin/python3
/usr/bin/python3

装了多个版本时用 -a 全列出来,排在最前面的才是实际生效的那个 想换掉,改 $PATH 的顺序,不要去动文件

2. which 查不到的东西

Terminal window
which cd # 无输出,返回 1
type cd # cd is a shell builtin

3. 脚本里判断命令存不存在

Terminal window
command -v git >/dev/null || { echo "需要先安装 git"; exit 1; }

which 不是每个系统都装了,返回值和输出格式也不统一 POSIX 标准的做法是 command -v,它还能查到别名、函数和内建命令

4. 顺着位置继续查

Terminal window
ls -l "$(which python3)" # 是不是软链接
readlink -f "$(which python3)" # 软链接最终指向哪
file "$(which python3)" # 是二进制还是脚本
  • man which
  • help type(shell 内建,which 查不到它)