Linux

find、grep 与脚本入门

RHEL 9 查找文件用 find,过滤文字用 grep,把多条命令写进 .sh 脚本一次执行;附新手向逐步说明与练习。

这一篇解决三个新手高频问题:

  1. 文件在哪? → find
  2. 文件里有没有某句话? → grep
  3. 每次都敲同样几条命令,能不能一次做完? → 脚本

会用 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 \;

一步步读:

  1. find /usr -type f -perm -g=s —— 先找出来(只找文件)
  2. 对每一个结果执行 cp -p 找到的文件 /root
  3. 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 里有没有 tomgrep
在很多日志里找含 Error 的文件名先 find 缩小范围,再 grep(进阶)

三、脚本:把命令写进文件一次跑完

为什么需要脚本

假设每次装完系统都要:

  1. 建目录
  2. 拷配置
  3. 打包备份
  4. 建用户

敲 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。

脚本出错怎么排查

脚本会一条条往下执行。某一行失败时:

  1. 看终端报错,定位是哪一行
  2. 单独把那一行拷出来手敲,看是不是路径/权限问题
  3. 改完再 ./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、sub
  • grep 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 即可。

小结

  1. 找文件名 用 find,找文件里的字 用 grep。
  2. find 会递归往下找;grep -r 是在内容里递归。
  3. 脚本 = 把命令写进 .sh,chmod +x 后用 ./脚本名 执行。
  4. 先小范围 find/grep 看结果,再考虑 -exec 或写进脚本。

下一篇进入磁盘:分区、格式化、挂载,以及考试高频的 LVM 扩容。


系列导航:总目录 · 上一篇:sudo 与找回 root · 下一篇:分区与 LVM

相关阅读

全部文章 →
← 返回列表更多「Linux」