草稿待审:locate (plocate) 本机无索引数据库,基于文档核查,尚未实际执行;rpm -qf 为 RPM 系发行版命令,本机 Ubuntu 未安装 rpm,基于文档核查;其余命令 (which、whereis、type、command -v、readlink、realpath、find、dpkg -S) 均在 WSL2 Ubuntu 24.04 实测通过。
在 Linux 上定位命令的可执行文件路径,不同工具的搜索范围与输出格式差异很大。
选错工具会得到别名定义、符号链接或手册页路径,而非真正执行的二进制。本文按命令类型分场景,给出可直接运行的命令与预期输出。
命令类型与选型对照
Shell 会按固定顺序解析命令:别名 → 关键字 → 函数 → 内建命令 → PATH 中的外部可执行文件 [3]。不同定位工具覆盖的范围不同:
| 命令类型 | 推荐工具 | 典型输出 |
|---|---|---|
| 别名 | type / command -v |
alias ll='ls -l' |
| Shell 内建 | type / command -v |
cd is a shell builtin |
| Shell 函数 | type / command -v |
函数定义 |
| 外部可执行文件 | which / type -P / command -v |
/usr/bin/ls |
| 符号链接目标 | readlink -f / realpath |
/usr/bin/python3.12 |
| 包归属 (Debian/Ubuntu) | dpkg -S <绝对路径> |
coreutils: /usr/bin/ls |
| 包归属 (RPM 系) | rpm -qf <绝对路径> |
coreutils-... (基于文档核查) |
which 与 whereis
which 只在 PATH 中搜索可执行文件,不识别别名或函数,也不解析符号链接 [1]。
whereis 搜索二进制、源码与手册页,范围比 which 更广 [2]:
which ls
which -a sh
whereis ls
whereis -b ls
whereis -m ls
which ls输出/usr/bin/lswhich -a sh列出 PATH 中所有同名可执行文件,如/usr/bin/sh与/bin/sh- 退出码:0 全部找到,1 有未找到,2 选项非法 [1]
whereis ls输出ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz-b仅二进制,-m仅手册页,-s仅源码- 可用
-B/-M/-S指定额外搜索目录,-f终止目录列表 [2]
type 与 command -v
type 是 Bash 内建,能识别别名、关键字、函数、内建与外部命令 [3]。command -v 与 command -V 用于脚本中判断命令类型 [3]:
type ls
type cd
type if
shopt -s expand_aliases
alias ll='ls -l'
type ll
type -P ls
command -v ls
command -v cd
command -V ls
type ls→ls is /usr/bin/lstype cd→cd is a shell builtintype if→if is a shell keywordtype ll→ll is aliased to 'ls -l'type -P ls→/usr/bin/ls(仅输出 PATH 中的外部命令路径,别名/函数返回空)command -v ls→/usr/bin/lscommand -v cd→cd(内建命令只输出名称)command -V ls→ls is /usr/bin/ls(更详细的描述)
脚本中推荐用 command -v 做存在性检查,因为它对别名、内建、外部命令都有效且输出稳定。
readlink 与 realpath
当命令是符号链接时,which 只给出链接路径,需用 readlink 或 realpath 解析到真实文件 [4][5]:
readlink -f /usr/bin/python3
realpath /usr/bin/python3
readlink -e /tmp/nonexistent 2>/dev/null; echo "exit=$?"
readlink -f逐级解析所有符号链接,最终文件不存在时仍输出推导路径readlink -e要求最终文件存在,否则输出空并返回非零realpath默认行为等同readlink -f;realpath -e等同readlink -e- 实测:
/usr/bin/python3→/usr/bin/python3.12
全盘搜索与包归属
PATH 之外的文件用 find 或 locate 搜索 [6][7];已知绝对路径可反查所属包 [8]:
find /usr/bin -maxdepth 1 -name 'ls' -type f
locate -l 5 ls
dpkg -S /usr/bin/ls
dpkg -L coreutils | grep -E '/ls$'
find直接遍历目录,无需索引,适合精确搜索locate依赖updatedb构建的索引,查询极快但无法找到索引更新后新增的文件;本机无索引数据库,该命令基于文档核查 [7]dpkg -S /usr/bin/ls→coreutils: /usr/bin/lsdpkg -L coreutils列出包内所有文件
RPM 系发行版 (CentOS/RHEL/Fedora) 对应命令为 rpm -qf /usr/bin/ls [9],本机 Ubuntu 未安装 rpm,该命令基于文档核查。
排错速查表
| 现象 | 原因 | 处理 |
|---|---|---|
which 找不到已安装命令 |
PATH 未包含该目录或 shell 未刷新 | echo $PATH;hash -r 清除命令缓存后重试 |
type 报 not found 但命令可运行 |
别名未在非交互 shell 展开 | 脚本中用 shopt -s expand_aliases 或改用 command -v |
readlink -f 输出路径但文件不存在 |
链接链断裂或目标被删除 | 改用 readlink -e 校验最终文件存在 |
locate 无输出或报数据库缺失 |
未运行 updatedb |
sudo updatedb 后重试,或改用 find |
dpkg -S 返回大量不相关结果 |
传入的是文件名而非绝对路径 | 务必传绝对路径,如 /usr/bin/ls |
which -a 与 type -a 结果不同 |
which 不识别别名/函数 |
需要覆盖别名/函数时用 type -a |
附录
- 测试机:WSL2 Ubuntu 24.04.4 LTS
- 内核:Linux 6.6.114.1-microsoft-standard-WSL2
- 测试日期:2026-11-05
- 观察结果:
which ls→/usr/bin/ls;which -a sh→/usr/bin/sh与/bin/sh;whereis ls→/usr/bin/ls /usr/share/man/man1/ls.1.gz;type ls/cd/if分别输出外部/内建/关键字;别名在shopt -s expand_aliases下被type与command -v正确识别;type -P对别名返回空;readlink -f与realpath均将/usr/bin/python3解析为/usr/bin/python3.12;find /usr/bin -maxdepth 1 -name 'ls'→/usr/bin/ls;dpkg -S /usr/bin/ls→coreutils: /usr/bin/ls;locate因无索引数据库未实测;rpm未安装未实测。 - 本文所有命令均为只读查询,不修改系统,无需回滚。
常见问题
- 问:脚本里该用
which还是command -v?
优先 command -v。它覆盖别名、内建、函数与外部命令,输出更稳定;which 仅搜索 PATH 且在部分发行版上是外部脚本,行为略有差异。
- 问:
readlink -f和realpath有什么区别?
日常用途等价。realpath 来自 coreutils,选项更丰富(如 -m 允许路径不存在);readlink 来自 util-linux,-e/-f 语义清晰。两者都比 ls -l 解析链接更可靠。
- 问:如何确认命令到底执行了哪个文件?
用 type -a <命令> 查看全部候选,再用 readlink -f $(type -P <命令>) 解析符号链接。type -P 确保只取 PATH 中的外部命令,避免别名干扰。
- 问:
locate找不到刚安装的程序怎么办?
运行 sudo updatedb 更新索引,或改用 find / -name '<文件名>' 2>/dev/null 直接遍历。
- 问:如何从命令反查安装包?
Debian/Ubuntu 用 dpkg -S $(readlink -f $(type -P <命令>));RPM 系用 rpm -qf $(readlink -f $(which <命令>))。务必传绝对路径。
参考资料
- [1] which(1) — debianutils — Debian testing(which)
- [2] whereis(1) — util-linux — Ubuntu noble(whereis)
- [3] bash(1) — GNU Bash — Ubuntu noble(bash)
- [4] readlink(1) — coreutils — Ubuntu noble(readlink)
- [5] realpath(1) — coreutils — Ubuntu noble(realpath)
- [6] find(1) — findutils — Ubuntu noble(find)
- [7] plocate(1) — plocate — Ubuntu noble(plocate)
- [8] dpkg(1) — dpkg — Ubuntu noble(dpkg)
- [9] rpm(8) — Linux manual page(rpm)
文中主要命令已在 WSL Ubuntu(24.04)实测并核对其在 Debian 系与通用发行版的文档口径。