在日常运维工作中,有一件事我们几乎每天都在做——找文件。
日志文件不知道塞在哪个目录下了?某个配置文件改了但忘了放哪?想看看系统里有没有安装某个命令?这时候如果没有一个好用的搜索方法,就只能 ls 一层一层往下翻,翻到怀疑人生。
今天这期,我们把 Linux 下最常用的 6 个搜索命令一次性讲清楚:find、xargs、locate、whereis、which、whatis。搞懂了它们,以后找东西再也不用靠猜。
一、find:全盘搜索利器
说到找文件,find 是 Linux 下最强大的搜索命令,没有之一。它的核心原理很朴素:从你指定的目录开始,一层一层往下扫,把所有符合条件的文件都列出来。
基本语法:
find [搜索路径] [条件参数] [动作]
先来看最常用的几个参数:
1. 按文件名搜索(-name)
这是最直观的需求——"帮我找一个叫 xxx 的文件":
find /etc -name "*.conf"
这条命令会在 /etc 目录下找所有以 .conf 结尾的文件。-name 支持通配符:* 匹配任意字符,? 匹配单个字符。比如 -name "a??.txt" 可以匹配 abc.txt,但不会匹配 ab.txt。
注意 -name 是区分大小写的。如果你想忽略大小写,用 -iname:
find /usr -iname "README"
这样 README、readme、ReadMe 都能匹配到。
2. 按文件类型搜索(-type)
Linux 里一切皆文件,但文件分很多种。你可以用 -type 指定只要某种类型:
-
-type f:普通文件-
-type d:目录-
-type l:符号链接-
-type b:块设备-
-type c:字符设备-
实际工作中最常见的用法是组合起来用:
find /var/log -name "*.log" -type f
意思是:在 /var/log 下找所有 .log 结尾的普通文件。如果目录里有个叫 error.log.bak 的目录(虽然不太可能),就不会被匹配到,因为 -type f 排除了目录。
3. 按时间搜索(-mtime / -atime / -ctime)
运维场景中经常需要按时间筛选文件,比如"找 7 天前的日志来清理"。这时候 -mtime 就派上用场了:
find /home -name "*.log" -type f -mtime +7
关于时间参数有个容易搞混的地方:
-
-mtime +7:7 天以前修改过的文件(不包含第7天)-
-mtime -7:7 天以内修改过的文件-
-mtime 7:刚好在第 7 天修改过的文件-
类似的还有 -atime(按访问时间)和 -ctime(按状态改变时间,比如权限变更)。还有个更精确的 -mmin,按分钟算,适合更细粒度的搜索。
4. 按文件大小搜索(-size)
磁盘快满了,想找出大文件来清理?
find / -type f -size +100M
这会列出全系统所有超过 100MB 的文件。-size 的单位:
5. 按权限搜索(-perm)
想排查有安全风险的权限设置,可以用 -perm:
find /home -perm 777 -type f
找出所有权限为 777 的文件,这些文件任何人可读写执行,安全风险较高。
更实用的用法是找所有用户可执行的文件:
find /usr -perm -o+x -type f
注意这里 -perm -o+x 用的是短横线前缀,表示"至少包含其他用户执行权限"。
6. 多条件组合(-and / -or / -not)
搜索条件可以组合使用:
find /var -name "*.log" -type f -size +50M -mtime +30
找出 /var 下超过 50MB 且超过 30 天的日志文件——这正是磁盘清理的黄金组合。
用 -or 可以表达"满足任一条件":
find /tmp -name "*.tmp" -o -name "*.cache" -type f
用 -not 可以排除某些结果:
find /etc -name "*.conf" -not -name "nginx*"
找出所有 .conf 文件,但排除名字以 nginx 开头的。
7. 搜索后执行动作(-exec / -delete / -print)
find 找到文件之后,默认就是打印出来(-print)。但更强大的地方在于可以执行命令:
find /tmp -name "*.tmp" -type f -exec rm {} \;
-exec 后面的命令会对每个匹配到的文件执行。花括号 {} 代表找到的文件路径,\; 是固定结尾,告诉 -exec 命令到此结束。
有个更安全的变体 -exec ... {} +,它会把所有文件一次性传给命令,效率更高:
find /var/log -name "*.gz" -exec rm -f {} +
上面这个例子展示了 find 的典型用法:在 /home 下搜索所有超过 7 天的 .log 文件,结果一目了然。
⚠️ 注意:find 配合 xargs,威力翻倍
前面讲了 -exec,但它有个缺点——每找到一个文件就执行一次命令。如果要处理 1000 个文件,就会执行 1000 次,效率很低。而且遇到文件名里有空格或特殊字符时,-exec 容易出问题。
这时候就该 xargs 登场了。
xargs 的工作逻辑很简单:它从标准输入读取数据(一行或多行),然后把它们拼成一条命令的参数列表,一次性执行。说白了,它就是把"一列文件名"变成"一条命令的参数"。
来看经典组合:
find /tmp -name "*.tmp" -type f | xargs rm -v
这条命令的执行流程是:
-
find 找到所有 .tmp 文件,把路径一行一行输出-
- 管道
| 把这些路径传给 xargs -
xargs 把所有路径拼接到 rm -v 后面-
- 最终执行的是类似
rm -v /tmp/a.tmp /tmp/b.tmp /tmp/c.tmp 的一条命令 -
结果就是我们截图里看到的样子,每个文件都被 rm -v 逐个显示删除过程,但背后只调用了一次 rm。
xargs 常用参数
-p 确认模式:执行前让你确认,适合危险操作:
find /tmp -name "*.tmp" | xargs -p rm
它会先列出要执行的命令,问你 "?... ",你输入 y 才真正执行。
-n 限制每次参数数量:限制每次命令最多传几个参数:
find /data -type f | xargs -n 5 ls -l
这样每次 ls -l 只会列出 5 个文件的详细信息。
-I 替换字符串:当你需要把输入放到参数中间而不是末尾时使用:
find /backup -name "*.sql" | xargs -I {} mv {} /backup/daily/
-I {} 表示把输入内容放在 {} 的位置上。注意 -I 会强制每次只传一个参数(相当于 -n 1)。
-0 处理特殊文件名:最推荐的安全写法——配合 find -print0:
find /data -name "* *" -print0 | xargs -0 ls -l
这是生产环境最推荐的写法。-print0 让 find 用空字符 \0 而不是换行符分隔文件名,xargs -0 也按空字符解析。这样文件名里有空格、换行甚至单引号都不会出问题。
-t 显示执行的命令:排错时很有用:
echo "file1 file2 file3" | xargs -t rm
它会先打印出 rm file1 file2 file3,让你看到实际执行的命令是什么。
-d 自定义分隔符:
echo "a,b,c" | xargs -d "," -n 1 echo
按逗号分隔,每次 echo 一个。
xargs 不只是配合 find
xargs 其实是个通用的"输入转参数"工具,可以配合任何输出列表的命令:
cat servers.txt | xargs -I {} ssh {} "uptime"
从文件读取服务器列表,逐台执行 uptime 查看运行时间。
docker ps -q | xargs docker stop
一键停止所有运行中的容器。
二、locate:闪电搜索,快得不讲理
如果说 find 是个认真的图书管理员,一本一本翻书架;那 locate 就是直接查目录卡片——速度不是一个级别的。
locate 的原理很简单:它不直接扫描文件系统,而是查一个预先建好的数据库(通常在 /var/lib/mlocate/mlocate.db)。这个数据库由 updatedb 命令定期更新(一般通过 cron 每天跑一次),里面存了系统里所有文件的路径。
基本用法:
locate nginx.conf
它会搜索整个数据库,找出所有路径中包含 nginx.conf 的文件。速度极快,几乎是瞬间出结果,因为它不需要真的去翻硬盘。
locate 常用参数
-c 只统计数量:不显示具体路径,只告诉你找到多少个:
locate -c "*.conf"
-i 忽略大小写:
locate -i ReadMe
-l 限制显示数量:
locate -l 5 "*.log"
只显示前 5 条结果,适合结果特别多的时候。
-e 只返回实际存在的文件:
locate -e "*.tmp"
因为数据库可能不是最新的,有些文件可能已经被删除了。加 -e 可以验证文件是否真的还在。
--regex 正则匹配:
locate --regex "\.log$"
用正则表达式匹配,\.log$ 表示路径以 .log 结尾。
手动更新数据库
如果你刚创建了一个文件,想立刻用 locate 搜到,需要先手动更新数据库:
sudo updatedb
这个过程可能需要几秒到几十秒,取决于文件数量。这也是 locate 唯一的短板——搜索结果不是实时的。如果你需要找刚刚创建的文件,还是得用 find。
三、whereis、which、whatis:查命令,不是查文件
前面讲的 find 和 locate 是通用的文件搜索工具,但有时候我们的需求更具体——"我想找个命令装在哪?""这个命令是干嘛的?" 这时候就需要专门查命令的工具了。
1. which:找命令的可执行文件路径
which 做的事很简单:在 $PATH 环境变量列出的目录里,找某个命令的可执行文件在哪。
which python3
/usr/bin/python3
它只返回第一个匹配到的路径。如果你装了多个版本的 python3,which 只会告诉你 $PATH 里排在最前面的那个。
-a 参数:显示所有匹配的路径:
which -a python3
这样你就能看到系统里所有 python3 可执行文件的位置,帮你搞清楚到底在用哪个版本。
2. whereis:找命令的一切
whereis 比 which 查得更全面。它不只找可执行文件,还会找二进制文件、源码、man 手册:
whereis python3
python3: /usr/bin/python3 /usr/lib/python3.11 /usr/share/man/man1/python3.1.gz
输出分为三部分:可执行文件路径、库文件目录、man 手册路径。一目了然。
-b 只看二进制文件:
whereis -b nginx
-m 只看 man 手册:
whereis -m ls
-s 只看源码:
whereis -s gcc
whereis 的搜索范围是预设的系统目录,比 find 快,但不会搜索 $PATH 以外的自定义目录。
3. whatis:一句话解释命令
遇到一个不认识的命令,第一反应是 man 它。但如果你连它是干嘛的都不知道,直接看 man 手册可能太重了。这时候 whatis 最合适:
whatis ls
ls (1) - list directory contents
它从 man 手册的 NAME 部分提取一句话简介,告诉你这个命令是干什么的。括号里的 (1) 表示它属于 man 手册的第 1 章节(用户命令)。
man 手册的章节划分:
-
- 第 1 章:用户命令(ls, cp, find 等)
-
- 第 2 章:系统调用
-
- 第 3 章:库函数
-
- 第 4 章:特殊文件(设备文件)
-
- 第 5 章:文件格式和约定
-
- 第 6 章:游戏
-
- 第 7 章:杂项(协议、字符集等)
-
- 第 8 章:系统管理命令
-
-w 只显示 man 手册路径:
whatis -w find
上面截图展示了三个命令的实际效果:which 告诉你可执行文件在哪,whereis 给出更全面的信息,whatis 用一句话解释命令用途。
四、六个命令一张表,帮你快速决策
讲了这么多,实际用的时候该选哪个?看这张表就明白了:
| 命令 |
用途 |
速度 |
实时性 |
find |
全盘搜索文件,支持各种条件 |
较慢(实时扫描) |
实时 |
xargs |
把输入列表转为命令参数 |
快 |
实时 |
locate |
按文件名快速搜索 |
极快(查数据库) |
非实时 |
whereis |
查找命令的二进制、源码、man |
快 |
准实时 |
which |
查找命令在 $PATH 中的位置 |
快 |
实时 |
whatis |
一句话解释命令用途 |
极快 |
准实时 |
简单记忆法:
-
- 找文件,条件复杂 → 用
find -
- 找文件,知道名字,要快 → 用
locate -
- 批量处理 find 的结果 →
find | xargs -
- 找命令装在哪 → 用
which -
- 找命令的一切(含手册) → 用
whereis -
- 想知道命令是干嘛的 → 用
whatis -
💡 总结一下
Linux 的搜索命令各有分工,find 和 locate 是找文件的主力,which、whereis、whatis 是查命令的三剑客,而 xargs 则是连接搜索与操作的桥梁。
日常工作中最实用的组合莫过于 find ... -print0 | xargs -0 ...,这个管道几乎能解决所有"找到文件然后批量处理"的需求。建议把这组搭档刻在肌肉记忆里。
觉得有用就点个「在看」,分享给身边也在用 Linux 的朋友吧 👇