find、grep 与脚本入门
RHEL 9 查找文件用 find,过滤文字用 grep,把多条命令写进 .sh 脚本一次执行;附新手向逐步说明与练习。
本页目录
这一篇解决三个新手高频问题:
- 文件在哪? →
find - 文件里有没有某句话? →
grep - 每次都敲同样几条命令,能不能一次做完? → 脚本
会用 ls、cd 就能看懂;命令都给了「是什么 → 怎么敲 → 看结果」。
系列:从 RHCSA 到 RHCE · 第 9 / 17 篇 上一篇:sudo 与找回 root 下一篇:分区与 LVM 总目录:系列索引
环境说明
- 系统:RHEL 9
- 身份:实验用 root 也行;只查自己家目录用普通用户也可以
- 前置:会打开终端、会
cd/ls
一、find:按条件找文件
它是什么
find 会从你指定的目录开始,一层层往下找,把符合条件的文件/目录列出来。
基本格式:
find 从哪里找 按什么条件
先来一个「不写条件」的
find /etc
会列出 /etc 下所有东西(可能很长)。日常几乎都要加条件。
按名字找:-name
find /etc -name hosts
含义:在 /etc 下,名字正好叫 hosts 的有哪些。
想「名字以 hosts 开头」:
find /etc -name "hosts*"
| 写法 | 含义 |
|---|---|
| hosts | 整个名字必须完全一样 |
| "hosts*" | 以 hosts 开头,后面随便 |
| "*.conf" | 以 .conf 结尾 |
新手注意:带
*时外面要加引号,否则 shell 可能先替换成当前目录里的文件名,结果就不对了。
find /etc -name "*.conf"
find /etc -name "yum*"
按类型找:-type
| 条件 | 含义 |
|---|---|
| -type f | 普通文件 file |
| -type d | 目录 directory |
| -type l | 链接文件 link |
find /etc -name "yum*" -type f
find /etc -name "yum*" -type d
可以多个条件一起写,表示「同时满足」。
按大小、属主、权限(考试也常见)
find /etc -type f -size +1M # 大于 1MB 的文件
find /etc -user root -type d # 属主是 root 的目录
find /usr -perm -g=s # 权限里带 sgid 的
| 条件 | 例子 | 含义 |
|---|---|---|
| -size | +10M -10k 1M | 大于 / 小于 / 约等于 |
| -user | -user tom | 属主是谁 |
| -perm | -perm 644 等 | 按权限找(细节见 ACL 与特殊权限) |
找到以后还能做事:-exec
语法要记牢(固定写法):
find 从哪找 条件 -exec 命令 {} \;
| 符号 | 含义 |
|---|---|
| {} | 每一个「找到的文件」会替换到这里 |
| ; | 告诉 find:命令到这里结束(必须有空格和分号) |
例子:把 /usr 下带 sgid(组特殊位,见权限篇)的文件拷到 /root,并保留原权限:
find /usr -type f -perm -g=s -exec cp -p {} /root \;
一步步读:
find /usr -type f -perm -g=s—— 先找出来(只找文件)- 对每一个结果执行
cp -p 找到的文件 /root cp -p表示拷贝时保留权限和时间等属性
新手建议:先不带
-exec只find看列表,确认没找错,再加-exec。
二、grep:在文件内容里找字
它是什么
find 找的是文件名;grep 找的是文件里的文字。
grep 关键词 文件
grep root /etc/passwd
含义:打开 /etc/passwd,把包含 root 这几个字的行打印出来;其它行不显示。
grep bash /etc/passwd
只要「以某字开头 / 结尾」
| 写法 | 含义 |
|---|---|
| "^root" | 这一行以 root 开头 |
| "bash$" | 这一行以 bash 结尾 |
| ^ | 行首(固定符号) |
| $ | 行尾(固定符号) |
grep "^root" /etc/passwd
grep "bash$" /etc/passwd
记忆:尖帽子
^像在行的最前面「顶」着;$在英语里常表示「结尾」。
在整个目录里搜:-r
默认 grep 只看你写的那一个文件。要在一个文件夹(含子文件夹)里搜:
grep -r hello /tmp/lab09
-r = recursive 递归。结果会带上「文件名:」方便你看是从哪来的。
grep -ri error /tmp/lab09 # -i 忽略大小写,再加 -r
把结果存成文件:重定向
终端上的输出可以「倒进」一个文件:
| 符号 | 含义 |
|---|---|
| > | 覆盖写入(文件不存在就新建;存在就清空重写) |
| >> | 追加(加在文件末尾,不清空) |
想把文件内容打到屏幕上,用 cat 文件名(查看短文本;见 基础命令)。
grep root /etc/passwd > /tmp/passbak
cat /tmp/passbak
grep adm /etc/passwd > /tmp/passbak # 覆盖,之前的内容没了
cat /tmp/passbak
grep root /etc/passwd >> /tmp/passbak # 追加
cat /tmp/passbak
find 和 grep 怎么选?
| 你想… | 用 |
|---|---|
| 找名叫 sshd_config 的文件在哪 | find |
| 看 passwd 里有没有 tom | grep |
| 在很多日志里找含 Error 的文件名 | 先 find 缩小范围,再 grep(进阶) |
三、脚本:把命令写进文件一次跑完
为什么需要脚本
假设每次装完系统都要:
- 建目录
- 拷配置
- 打包备份
- 建用户
敲 20 遍又累又容易错。可以把命令按顺序写进一个文件,再执行这个文件——这就是脚本。
最小例子
vim /root/test.sh
输入(建议原样抄):
#!/bin/bash
mkdir -p /test/tools
touch /test/tools/rhel.txt
chmod 000 /test/tools/rhel.txt
chown :adm /test/tools/rhel.txt
cp -r /etc /test/tools/
tar -czf /test/tools/etc.tar.gz /etc
useradd rhel8
useradd rhel9
echo redhat | passwd --stdin rhel9
保存退出(:wq)。
说明:
echo redhat | passwd --stdin rhel9是把密码redhat管道给passwd,一次性给用户rhel9设密码(RHEL 常用写法)。tar -czf是打包并 gzip,见 dnf 软件源与 tar。
| 行 | 你在干什么 |
|---|---|
| #!/bin/bash | 用 bash 来跑这个脚本(第一行固定) |
| 后面每一行 | 和你手敲的一样,一行一条命令 |
给执行权限并运行
chmod +x /root/test.sh
ls -l /root/test.sh
cd /root
./test.sh
| 写法 | 含义 |
|---|---|
| ./test.sh | 执行当前目录下的 test.sh |
| /root/test.sh | 用绝对路径执行 |
| sh test.sh | 用 sh 解释器跑(有时也可以) |
易错:没有
chmod +x时会提示 Permission denied。 易错:当前目录不在/root时写test.sh会找不到,要用./test.sh或全路径。 扩展名:.sh是习惯,不是强制;但考试和团队里建议都带.sh。
脚本出错怎么排查
脚本会一条条往下执行。某一行失败时:
- 看终端报错,定位是哪一行
- 单独把那一行拷出来手敲,看是不是路径/权限问题
- 改完再
./test.sh(注意:已经执行过的useradd可能已存在,再跑会报错——这是正常的)
四、串起来:新手练习(约 25 分钟)
在 /tmp 下做,避免动系统文件。
cd /tmp
mkdir -p lab09
cd lab09
# 准备几个文件
echo "hello root" > a.txt
echo "hello tom" > b.txt
echo "nothing here" > c.txt
mkdir sub
# 注意:下面一行是「大写 E 的 Error」,方便演示 grep -i
echo "Error: disk full" > sub/app.log
# find:按名字
find /tmp/lab09 -name "*.txt"
find /tmp/lab09 -type f
find /tmp/lab09 -type d
# grep:按内容
grep hello /tmp/lab09/a.txt
grep -r hello /tmp/lab09 # -r 递归,目录下所有文件里找
grep "^hello" /tmp/lab09/a.txt
grep disk /tmp/lab09/sub/app.log
# 下面这条:小写 error,文件里是 Error,默认区分大小写 → 无输出
grep error /tmp/lab09/sub/app.log
# 加上 -i 忽略大小写 → 能找到
grep -i error /tmp/lab09/sub/app.log
# 重定向
grep hello /tmp/lab09/*.txt > /tmp/lab09/found.txt
cat /tmp/lab09/found.txt
# 小脚本
vim /tmp/lab09/myscript.sh
myscript.sh 内容:
#!/bin/bash
echo "script start"
mkdir -p /tmp/lab09/out
cp /tmp/lab09/a.txt /tmp/lab09/out/
tar -czf /tmp/lab09/out/pack.tar.gz /tmp/lab09/a.txt /tmp/lab09/b.txt
echo "script done"
chmod +x /tmp/lab09/myscript.sh
/tmp/lab09/myscript.sh
ls -l /tmp/lab09/out
期望
find能列出 a.txt、b.txt、c.txt、subgrep hello在 a.txt、b.txt 里有结果;c.txt 没有grep disk能在 app.log 里找到grep error(小写)无输出;grep -i error能找到大写的Error- 脚本跑完后
out/里有拷过去的 a.txt 和pack.tar.gz
五、速查表
| 目标 | 命令 |
|---|---|
| 按名找文件 | find /path -name "名字" |
| 只要文件/目录 | find /path -type f / -type d |
| 大文件 | find /path -type f -size +100M |
| 对结果执行命令 | find ... -exec 命令 {} ; |
| 文件里找字 | grep 关键词 文件 |
| 忽略大小写 | grep -i 关键词 文件 |
| 目录里递归找 | grep -r 关键词 目录 |
| 行首/行尾 | grep "^xx" / grep "xx$" |
| 输出存文件 | 命令 > 文件 或 >> 文件 |
| 新建脚本 | vim xx.sh → 内容 → chmod +x xx.sh → ./xx.sh |
考点与易错
考点:
find -name、-type、-exec ... {} \;;grep的^$;脚本chmod +x后./执行。 易错:-name "*.conf"忘记引号。 易错:-exec末尾写成;而不是\;(要转义,且前面有空格)。 易错:把>和>>用反,把重要文件覆盖没了。 易错:脚本没有执行权限,或当前目录下没有写./。 练习环境:课堂若在red上操作,路径换成你的家目录或/tmp即可。
小结
- 找文件名 用
find,找文件里的字 用grep。 find会递归往下找;grep -r是在内容里递归。- 脚本 = 把命令写进
.sh,chmod +x后用./脚本名执行。 - 先小范围
find/grep看结果,再考虑-exec或写进脚本。
下一篇进入磁盘:分区、格式化、挂载,以及考试高频的 LVM 扩容。
系列导航:总目录 · 上一篇:sudo 与找回 root · 下一篇:分区与 LVM