开篇:
"那个 nginx.conf 到底在哪?"------这是每个 Linux 新手和老手都会遇到的灵魂拷问。
有一次我接手一台"祖传"服务器,前同事把 Nginx 装在了编译目录里,配置文件既不在 /etc/nginx 也不在 /usr/local/nginx/conf。我用了三招定位:
bash
which nginx # 找到可执行文件在哪个目录
find / -name "nginx.conf" 2>/dev/null # 全盘找配置文件
三分钟内就锁定了目标。查找文件,是 Linux 运维和开发的高频刚需 。今天我们把 find、locate、which、whereis 四个查找命令一次讲透,并说清它们各自适合什么场景。
一、四个命令的定位:一张表先建立全局观
| 命令 | 查找对象 | 查找依据 | 速度 | 适用场景 |
|---|---|---|---|---|
find |
任意文件/目录 | 实时扫描目录树,按名字/类型/大小/时间等条件 | 慢(但功能最强) | 精确、复杂条件查找 |
locate |
文件名 | 查询预建数据库(updatedb) | 极快 | 模糊记得名字的快速查找 |
which |
可执行命令 | 搜索 PATH 环境变量 |
极快 | 命令装在哪个目录、是否已安装 |
whereis |
可执行命令及其文档 | 搜索标准目录 + PATH | 快 | 同时找二进制、源码、man 手册 |
一句话记忆:which/whereis 找命令,locate 快速找文件,find 精确找一切。
二、find:功能最强的"搜索机器"
语法格式
bash
find [起始路径] [匹配条件] [动作]
起始路径不写默认是当前目录 .。find 会递归遍历目录树,逐项匹配条件,最后执行动作(默认动作是打印路径)。
常用匹配条件
| 条件 | 说明 | 示例 |
|---|---|---|
-name "模式" |
按文件名(支持通配符,需加引号) | -name "*.log" |
-iname "模式" |
忽略大小写的文件名 | -iname "Readme*" |
-type f/d/l |
按类型:文件/目录/符号链接 | -type f |
-size +100M |
按大小(+ 大于、- 小于) |
-size +1G |
-mtime +7 |
按修改时间:7 天前(+7)/7 天内(-7) |
-mtime -1 |
-user 用户名 |
按属主 | -user www-data |
-perm 644 |
按权限 | -perm -4000(找 SUID) |
-maxdepth N |
限制递归深度 | -maxdepth 2 |
-empty |
空文件/空目录 | -empty |
常用动作
| 动作 | 说明 |
|---|---|
-print |
打印路径(默认动作) |
-exec 命令 {} \; |
对每个结果执行命令,{} 是结果占位符 |
-delete |
直接删除匹配的文件 |
-ls |
以 ls -l 格式列出详细信息 |
实战示例与预期输出
示例 1:按名字和类型查找
bash
find /etc -name "*.conf" -type f | head -5
预期输出:
/etc/rsyslog.conf
/etc/adduser.conf
/etc/deluser.conf
/etc/logrotate.conf
/etc/ucf.conf
示例 2:找出 7 天前修改的大日志文件
bash
find /var/log -name "*.log" -mtime +7 -size +100M -ls
这条命令把"超过 7 天没动过、且大于 100MB 的日志"列出来,配合第 92 篇的 logrotate 思路,就是清理磁盘的第一步。
示例 3:对结果批量执行命令------删除临时文件
bash
find /tmp -name "*.tmp" -type f -exec rm -f {} \;
这里 {} 逐个替换为找到的文件路径,\; 表示 -exec 命令结束(注意分号前有反斜杠)。
示例 4:统计某目录下普通文件数量
bash
find /var/log -type f | wc -l
预期输出(示例值):
128
⚠️ 常见错误与注意事项
-name的通配符必须加引号 :写成find / -name *.log时,Shell 会在 find 执行前先把*.log展开,往往匹配不到或匹配错误。正确写法是-name "*.log"。- 权限报错刷屏 :
find / -name x会遍历整个系统,遇到无权访问的目录会刷出一堆Permission denied。加2>/dev/null屏蔽错误输出。 -delete慎用 :它删除后不可恢复,务必先-print预览再删。-exec别忘{}和\;:格式写错会报find: missing argument to -exec。
三、locate:数据库加持的"秒查"
locate 的查找速度是"秒回",因为它不扫描磁盘,而是查询一个预先建好的文件名数据库。
语法格式
bash
locate [选项] 关键词
常用参数
| 参数 | 说明 |
|---|---|
-i |
忽略大小写 |
-c |
只输出匹配数量 |
-r 正则 |
用正则匹配 |
-n 数字 |
只显示前 N 条 |
示例与预期输出
示例:找名字里带 docker 的文件
bash
locate docker | head -10
预期输出(节选):
/etc/apparmor.d/docker
/etc/bash_completion.d/docker
/usr/bin/docker
/usr/share/man/man1/docker.1.gz
⚠️ 注意事项
数据库不会实时更新。刚创建的文件 locate 可能找不到,需要先更新数据库:
bash
sudo updatedb # Ubuntu/Debian
CentOS/Rocky 使用 yum install mlocate 安装后同样有 updatedb。另外有些发行版默认不装 locate(如新版 Ubuntu 用 plocate),装一下即可。
常见错误:以为
locate找不到就说明文件不存在------它可能只是数据库过期了。
四、which:命令"藏"在哪个目录
which 沿着 PATH 环境变量里的目录逐个查找,返回可执行命令的完整路径。
语法格式
bash
which [选项] 命令名
常用参数
| 参数 | 说明 |
|---|---|
-a |
显示所有匹配路径(PATH 中可能有多个同名) |
-i |
忽略大小写(GNU 版本) |
示例与预期输出
示例:查 python3 在哪、是否已安装
bash
which python3
预期输出:
/usr/bin/python3
如果没安装则无输出(退出码为 1)。因此 which 常被写进脚本做依赖检查:
bash
which git || { echo "git 未安装"; exit 1; }
小知识:
which只看PATH,如果某个命令是通过完整路径调用(如/opt/app/bin/tool),which tool是找不到的,用type -a tool或find兜底。
五、whereis:连源码和文档一起找
whereis 比 which 更进一步,它会去标准目录搜索,同时返回二进制、源码和 man 手册的位置。
语法格式
bash
whereis [选项] 命令名
常用参数
| 参数 | 说明 |
|---|---|
-b |
只找二进制文件 |
-m |
只找 man 手册 |
-s |
只找源码 |
示例与预期输出
示例:查 nginx 的所有相关文件
bash
whereis nginx
预期输出:
nginx: /usr/sbin/nginx /usr/share/man/man8/nginx.8.gz
如果你想看某个命令的手册位置,whereis -m ls 就能给出 /usr/share/man/man1/ls.1.gz。
六、知识扩展:find 的 -exec 与管道 xargs 的取舍
find -exec rm -f {} \; 和 find ... | xargs rm -f 都能批量处理结果,区别在哪?
| 对比项 | -exec ... \; |
管道 + xargs |
|---|---|---|
| 执行方式 | 每个文件起一个子进程 | 批量打包成参数,一次执行多次 |
| 处理特殊文件名 | 安全(逐项传参) | 需加 -print0 + -0 配合,否则空格/换行文件名会出错 |
| 速度 | 慢(进程开销大) | 快 |
推荐做法:文件名简单时用 xargs(配合 -print0 更稳) ,追求稳妥或文件少时用 -exec。关于 xargs 的深入用法(-n、-I、-P 并行),第 19 篇专门展开。
另一个知识点:find 的条件默认是 AND(与) ,比如 -name "*.conf" -type f 表示两个条件同时满足。如果要表达 OR,用 -o 并配合括号:find /etc \( -name "*.conf" -o -name "*.ini" \)。注意括号要转义或加引号,否则 Shell 会把它当子 shell。