跳到主要内容

Linux 命令初识第 3 课:查找与过滤

目标:会用 find 按名字 / 类型 / 大小 / 时间找文件,会用 grep 在文件和代码里搜内容,会用 wc 计数。 用时:约 40 分钟。全部在 Ubuntu 里敲。

两个命令的分工,一句话记住:

命令找什么典型问题
find找文件(按文件名、类型、大小、修改时间)「这个项目的配置文件放哪了?」
grep找文件里的内容(按文本)「日志里有哪些 ERROR?」「哪个文件定义了这个函数?」

0. 准备练习数据​

把下面整段复制到 Ubuntu 里执行,会在 ~/practice/lesson3 下生成一个模拟的商城项目和一份 302 行的日志:

mkdir -p ~/practice/lesson3 && cd ~/practice/lesson3
mkdir -p shop/{user,order,pay}/{handler,service} shop/{config,logs}
echo 'func GetUser(id int) {}' > shop/user/handler/user_handler.go
echo 'func FindUserByID(id int) {}' > shop/user/service/user_service.go
echo 'func CreateOrder() {}' > shop/order/handler/order_handler.go
echo 'func SaveOrder() {}' > shop/order/service/order_service.go
echo 'func Pay() {}' > shop/pay/handler/pay_handler.go
echo 'func CallBank() {}' > shop/pay/service/pay_service.go
printf 'port: 8080\nenv: dev\n' > shop/config/app-dev.yml
printf 'port: 80\nenv: prod\n' > shop/config/app-prod.yml
printf 'name: shop\nlog_level: info\n' > shop/config/app.yml
echo '# shop 商城后端' > shop/README.md
for i in $(seq 1 300); do
t="2026-10-20 10:$(printf %02d $((i / 6))):$(printf %02d $((i % 60)))"
if (( i % 50 == 0 )); then echo "$t [ERROR] order_id=$i pay failed: db timeout"
elif (( i % 20 == 0 )); then echo "$t [WARN] user_id=$((i % 7)) slow query 1200ms"
else echo "$t [INFO] GET /api/user/$((i % 7)) 200 15ms"
fi
done > shop/logs/app.log
echo "2026-10-20 11:00:00 [INFO] job finished, error_count=0" >> shop/logs/app.log
echo "2026-10-20 11:00:01 [INFO] retry ok, last error was resolved" >> shop/logs/app.log

这段脚本用到的循环、> 重定向等,第 4、5 课会讲,现在照抄即可。执行完用 tree shop 看一眼结构,再 head shop/logs/app.log 看看日志长什么样。


1. find —— 找文件​

find 找文件:搜索起点、名称、类型与查找深度

基本格式​

find 从哪找 按什么条件
find shop -name "*.go"

从哪找不写时默认是当前目录 .。find 会递归进入所有子目录。

常用条件​

条件含义例子
-name "模式"按文件名匹配,支持通配符,区分大小写find . -name "*.yml"
-iname "模式"同上,不区分大小写find . -iname "readme*"
-type f / -type d只要普通文件 / 只要目录find . -type d
-maxdepth N最多往下找 N 层find . -maxdepth 1 -type d
-size +10M大于 10M(-10M 小于;单位 k M G)find /var/log -size +1M
-mtime -1最近 1 天内修改过(+7 表示 7 天以前)find . -mtime -1
-empty空文件或空目录find . -type d -empty

多个条件写在一起,表示同时满足:

find shop -type f -name "*handler*" # 名字含 handler 的「文件」(不要目录)

⚠️ 两个坑​

  1. 通配符要加引号:写 -name "*.go",不要写 -name *.go。不加引号时,shell 会先在当前目录展开 *.go,传给 find 的就不是你想的那个模式了。
  2. 搜系统目录会刷屏报错:find / -name "nginx.conf" 会出现大量 Permission denied。可以加 sudo,或者在末尾加 2>/dev/null 把报错丢掉(原理第 4 课讲)。

了解即可:对找到的文件执行操作​

find . -name "*.tmp" -delete # 找到就删,非常危险,先不加 -delete 跑一遍
find . -name "*.go" -exec wc -l {} \; # 对每个找到的文件执行 wc -l,{} 代表文件名

2. grep —— 找内容​

grep 找内容:匹配行、行号、计数、上下文和文件名

基本格式​

grep [选项] 要找的文本 在哪些文件里
grep -n ERROR shop/logs/app.log

grep 会逐行检查,把包含这段文本的整行打印出来。

常用选项​

选项作用记忆
-n显示行号number
-i忽略大小写ignore case
-c只输出匹配的行数count
-v反选:输出不包含该文本的行invert
-w整词匹配:error 不会匹配到 error_count 里的 errorword
-r递归搜索整个目录recursive
-l只列出包含匹配的文件名list
-A 3 / -B 3 / -C 3同时显示匹配行之后 / 之前 / 前后 3 行After / Before / Context
-E扩展正则,可以用 | 表示「或」grep -E "ERROR|WARN"

后端最常用的几种组合​

grep -n "ERROR" app.log # 日志里所有错误,带行号
grep -c "ERROR" app.log # 错误有几条
grep -v "INFO" app.log # 去掉 INFO,只看值得关注的
grep -B 5 "ERROR" app.log # 出错前 5 行发生了什么(排查问题的关键!)
grep -rn "GetUser" . # 这个函数在项目里哪些地方出现
grep -rl "port" config/ # 哪些配置文件里配了 port
grep -E "ERROR|WARN" app.log # 错误或警告

关于引号​

要找的文本里有空格或特殊字符时,用引号括起来:

grep "db timeout" app.log # 正确:找 "db timeout"
grep db timeout app.log # 错误:会在名为 timeout 和 app.log 的文件里找 db

习惯上一律加引号,不会出错。


3. wc —— 计数​

计数与匹配易错点:wc、grep、which 与单词边界

word count,统计行数、单词数、字节数:

wc shop/logs/app.log # 行数 单词数 字节数 文件名
wc -l shop/logs/app.log # 只要行数 ← 最常用

预告:find 和 grep 的结果可以通过管道 | 交给 wc -l 计数,比如 find shop -name "*.go" | wc -l 数出 go 文件的个数。管道是第 4 课的内容,这里先感受一下。


4. 补充:找命令本身在哪​

which ls # /usr/bin/ls ← 敲 ls 时实际运行的是这个程序
which go # 没装 go 就什么都不输出

装完 Go、Java 后,遇到「命令找不到」或「版本不对」,第一步就是 which。


5. 跟着敲一遍​

cd ~/practice/lesson3
find shop -name "*.yml"
find shop -type d
find shop -type d -name "service"
find shop -maxdepth 1
find shop -type f -empty # 猜一猜:有没有空文件?
grep "WARN" shop/logs/app.log
grep -n "WARN" shop/logs/app.log
grep -c "WARN" shop/logs/app.log
grep -A 1 "order_id=50 " shop/logs/app.log
grep -r "func" shop
grep -rl "func" shop
grep "env" shop/config/*.yml # grep 也可以直接配合通配符搜多个文件
wc -l shop/logs/app.log
which grep

每敲一条,先猜结果,再看输出对不对。


6. 练习题​

题目在本文件夹的 题目解答.md 里,把每题的命令、输出和回答写在 解答: 下面,做完告诉我,我来批改。


7. 课后​

  • 提交:01-环境准备-01-linux命令初识-第3课查找与过滤