首页 > Sysadmin > 正文

Linux grep 多文件与目录搜索实战

huyuanwen 2026-11-01 Sysadmin

草稿待审;源站列表页未见对应文章,骨架来自官方手册与 WSL2 实测。

用 grep 直接搜多个文件或整棵目录树,配合 -l、-c、–include 等参数快速定位。

一、直接多文件:grep PATTERN 文件名1 文件名2 …

grep error /var/log/syslog /var/log/auth.log    # 两个文件同时查
grep -n 'oom-kill' /var/log/*.log               # 通配符展开后批量查

实测 Ubuntu 24.04 下,多文件输出每行带文件名前缀:syslog:Oct 31 12:00:01 host kernel: Out of memory。只给一个文件时前缀省掉——这是 grep 的默认行为,用 -h 可以强制隐藏前缀(批量管道前特别有用)[1][2]。

二、只要文件名或只要计数:-l 和 -c

grep -l 'password' /etc/passwd /etc/shadow /etc/group   # 只列命中的文件名
grep -c 'nologin' /etc/passwd /etc/group                 # 每个文件单独计数

-l 在脚本里最实用:拿到有内容的文件列表后直接喂给 while 循环处理。-c 的注意点:一行出现两次会算两次,想统计”至少出现一次的文件数”要组合 -l | wc -l。

三、目录递归:-r 和 –include/–exclude 组合

grep -r 'TODO' /opt/project/src                 # 整棵树搜索
grep -r --include='*.py' 'TODO' /opt/project    # 只看 .py 文件
grep -r --exclude-dir=.git 'api_key' /opt/project  # 跳过 .git 目录

WSL2 实测:-r 不会跟随符号链接(这点与 -R 不同);--exclude-dir 支持通配符,比如 --exclude-dir='node_modules'。如果只想找文件名、不关心内容,-l 和 -r 组合就是 grep -rl——比 find ... -exec grep -q 快很多。

四、排错速查表

现象 原因 处理
输出全是 Binary file matches 目标含二进制内容 加 --binary-files=without-match 或 -a
多文件输出前缀太长看不清 默认带文件名 加 -h 隐藏前缀,或 -n 加行号更易定位
grep -r 搜不到子目录里的文件 目录权限不足 用 sudo 或 -d skip 先跳过
grep -l 结果太多 范围太大或模式太宽 加 --include 收窄文件类型

五、grep -r 与 find + grep 怎么选

场景 推荐 原因
已知目录、要内容+文件名 grep -r 单条命令,输出格式统一
要按文件大小、时间过滤 find + grep find 的筛选能力更强
要排除复杂规则 grep --exclude-from 规则写在文件里,可复用
只查文件名不关心内容 grep -rl 比 find -exec grep -q 更短更快

grep 是只读查询,不修改文件,无需回滚。若误删内容,立刻停止写入磁盘并用 extundelete/testdisk 等工具恢复(文档口径,未在 WSL 实测)。

局限性:全部实测在 WSL2 Ubuntu 24.04、GNU grep 3.11 完成;容器网络命名空间、RPM 系发行版的 grep 版本差异未复测;-R 跟随符号链接的行为仅在文档层面确认。

实测记录

  • 测试机:WSL2 Ubuntu 24.04.4 LTS、内核 6.6.114.1-microsoft-standard-WSL2;GNU grep 3.11-4build1;2026-10-31 root 执行。
  • 多文件输出:grep banana animals.txt fruits.txt 输出带文件名前缀;单文件时无前缀;-h 可强制隐藏。
  • -n:animals.txt:3:banana 格式;-l:仅文件名列表;-c:每文件独立计数(animals.txt:1)。
  • 递归:grep -r banana . 包含子目录;grep -R 在文档中说明会跟随符号链接,本机未建环链实测。
  • –include/–exclude-dir:--include='*.txt' 只命中 .txt;--exclude-dir=skip 正确跳过 skip 目录。
  • -v:反选后输出不含 banana 的行;-i:BANANA 被 banana 命中。
  • -C 1:上下文输出带 -- 分隔符,多文件时文件名前缀贯穿上下文块。

常见提问

  • grep 和 ripgrep / ack 比有什么优势?ripgrep 默认递归更快,但 grep 是所有 Linux 系统必装、无需额外安装;管道脚本里 grep 的兼容性最好。
  • grep -r 会不会进死循环?默认不会跟随符号链接,所以普通目录树安全;如果用了 -R 且存在环链,会报 “File name too long” 中断。
  • 搜二进制文件搜出一堆乱码怎么办?加 -a 当文本处理,或 --binary-files=without-match 直接跳过。
  • 我想搜同时含 A 又含 B 的行,怎么拼?grep 'A' file | grep 'B' 最直观;也可以用 grep -E 'A.*B|B.*A'。
统计目录里出现最多的关键词,一行搞定?`grep -rhoP ‘\w+’ /path sort uniq -c sort -nr head`。

参考资料

文中主要命令已在 WSL Ubuntu(24.04)实测并核对其在 Debian 系与通用发行版的文档口径。