Linux 操作命令完全指南
环境 :华为云 ECS ecs-b97e-0001(2vCPU/4GiB/ac9.large.2) | Ubuntu 24.04 LTS | Linux 6.8.0 | Git 2.43.0
所有输出均为真实服务器终端输出 | 创建日期:2026-06-15
目录
- [实验一:ls / cd / pwd](#实验一:ls / cd / pwd)
- [实验二:mkdir / rm / mv / cp / cat / nl](#实验二:mkdir / rm / mv / cp / cat / nl)
- [实验三:more / less / head / tail](#实验三:more / less / head / tail)
- [实验四:which / whereis / locate](#实验四:which / whereis / locate)
- [实验五:find / xargs](#实验五:find / xargs)
- [实验六:wc / grep / 正则表达式](#实验六:wc / grep / 正则表达式)
- [实验七:cut / paste / tr](#实验七:cut / paste / tr)
- [实验八:sort / uniq / join](#实验八:sort / uniq / join)
- [实验九:comm / diff / patch](#实验九:comm / diff / patch)
- [实验十:df / du / time](#实验十:df / du / time)
- 命令速查表
实验一:ls / cd / pwd
1.1 知识点概览
┌─────────────────────────────────────────────────┐
│ Linux 目录导航三剑客 │
├──────────┬──────────┬───────────────────────────┤
│ pwd │ Print │ 显示当前工作目录绝对路径 │
│ │ Working │ -P: 显示物理路径(无视符号链) │
│ │ Directory│ -L: 显示逻辑路径(默认) │
├──────────┼──────────┼───────────────────────────┤
│ cd │ Change │ 切换工作目录 │
│ │ Directory│ cd - : 回到上次目录 │
│ │ │ cd ~ : 回到HOME │
│ │ │ cd / : 到根目录 │
├──────────┼──────────┼───────────────────────────┤
│ ls │ List │ 列出目录内容 │
│ │ │ -l: 长格式(权限/大小/时间) │
│ │ │ -a: 显示隐藏文件 │
│ │ │ -h: 人类可读大小 │
│ │ │ -R: 递归列出 │
│ │ │ -t: 按时间排序 │
│ │ │ -S: 按大小排序 │
│ │ │ -i: 显示inode号 │
│ │ │ -d: 只显示目录本身 │
└──────────┴──────────┴───────────────────────────┘
1.2 pwd --- 显示当前工作目录
bash
$ pwd
/tmp/cmd-lab-01
说明 :
pwd是最简单的命令,没有任何选项,直接输出当前所在目录的绝对路径。始终从根目录/开始。
1.3 cd --- 切换目录
bash
# 进入子目录
$ cd dir1 && pwd
/tmp/cmd-lab-01/dir1
# cd .. 返回上级
$ cd .. && pwd
/tmp/cmd-lab-01
# cd - 回到上次所在目录
$ cd dir2 && pwd
/tmp/cmd-lab-01/dir2
$ cd - && pwd
/tmp/cmd-lab-01
# cd ~ 回到家目录
$ cd ~ && pwd
/root
# 从根目录导航回来
$ cd / && ls -d tmp
tmp
$ cd /tmp/cmd-lab-01 && pwd
/tmp/cmd-lab-01
| 快捷方式 | 含义 | 说明 |
|---|---|---|
cd - |
回到上一次目录 | 使用 $OLDPWD 环境变量 |
cd ~ 或 cd |
回到 HOME 目录 | $HOME 变量指定 |
cd .. |
上级目录 | 每个目录都有 . 和 .. |
cd / |
根目录 | 文件系统顶层 |
1.4 ls --- 列出目录内容
首先创建测试环境:
bash
$ mkdir -p dir1 dir2 dir3
$ touch file1.txt file2.txt file3.log .hidden_file script.sh
$ ln -s file1.txt link_to_file1
ls 无参数:仅显示非隐藏文件名
bash
$ ls
dir1 dir2 dir3 file1.txt file2.txt file3.log link_to_file1 script.sh
ls -l:长格式(Long format),显示权限/硬链接数/所有者/组/大小/修改时间/文件名
bash
$ ls -l
total 12
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir1
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir2
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir3
-rw-r--r-- 1 root root 0 Jun 15 22:15 file1.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file2.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file3.log
lrwxrwxrwx 1 root root 9 Jun 15 22:15 link_to_file1 -> file1.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 script.sh
ls 权限字段解读 (以 -rw-r--r-- 为例):
- rw- r-- r--
│ │ │ └─ 其他用户权限 (r=读, - =无)
│ │ └─ 组权限
│ └─ 所有者权限
└─ 文件类型 (-=普通文件, d=目录, l=符号链接)
ls -a :显示隐藏文件(以 . 开头)
bash
$ ls -a
. .. dir1 dir2 dir3 file1.txt file2.txt file3.log .hidden_file link_to_file1 script.sh
关键发现 :
.hidden_file在ls中不可见,在ls -a中出现。
ls -lh:人类可读的大小格式
bash
$ ls -lh
total 12K
drwxr-xr-x 2 root root 4.0K Jun 15 22:15 dir1
drwxr-xr-x 2 root root 4.0K Jun 15 22:15 dir2
drwxr-xr-x 2 root root 4.0K Jun 15 22:15 dir3
-rw-r--r-- 1 root root 0 Jun 15 22:15 file1.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file2.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file3.log
lrwxrwxrwx 1 root root 9 Jun 15 22:15 link_to_file1 -> file1.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 script.sh
ls -R:递归列出子目录
bash
$ ls -R
.:
dir1 dir2 dir3 file1.txt file2.txt file3.log link_to_file1 script.sh
./dir1:
./dir2:
./dir3:
ls -lt:按修改时间排序(最新在前)
bash
$ ls -lt
total 12
lrwxrwxrwx 1 root root 9 Jun 15 22:15 link_to_file1 -> file1.txt
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir1
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir2
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir3
-rw-r--r-- 1 root root 0 Jun 15 22:15 file1.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file2.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file3.log
-rw-r--r-- 1 root root 0 Jun 15 22:15 script.sh
ls -ltr :按时间逆序(最旧在前)--- 运维常用,最新文件在最后一行
bash
$ ls -ltr
total 12
-rw-r--r-- 1 root root 0 Jun 15 22:15 script.sh
-rw-r--r-- 1 root root 0 Jun 15 22:15 file3.log
-rw-r--r-- 1 root root 0 Jun 15 22:15 file2.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file1.txt
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir3
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir2
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir1
lrwxrwxrwx 1 root root 9 Jun 15 22:15 link_to_file1 -> file1.txt
ls -lS:按文件大小排序(大文件在前)
bash
$ ls -lS
total 12
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir1
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir2
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir3
lrwxrwxrwx 1 root root 9 Jun 15 22:15 link_to_file1 -> file1.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file1.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file2.txt
-rw-r--r-- 1 root root 0 Jun 15 22:15 file3.log
-rw-r--r-- 1 root root 0 Jun 15 22:15 script.sh
ls -d:只显示目录自身,不列出其内容
bash
$ ls -ld dir1
drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir1
ls -i:显示 inode 号
bash
$ ls -li
total 12
395791 drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir1
395793 drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir2
395794 drwxr-xr-x 2 root root 4096 Jun 15 22:15 dir3
395795 -rw-r--r-- 1 root root 0 Jun 15 22:15 file1.txt
395796 -rw-r--r-- 1 root root 0 Jun 15 22:15 file2.txt
395797 -rw-r--r-- 1 root root 0 Jun 15 22:15 file3.log
395800 lrwxrwxrwx 1 root root 9 Jun 15 22:15 link_to_file1 -> file1.txt
395799 -rw-r--r-- 1 root root 0 Jun 15 22:15 script.sh
inode(索引节点) :每个文件在文件系统中的唯一编号。
link_to_file1 -> file1.txt的 inode 号(395800)与file1.txt(395795)不同,因为符号链接有自己的 inode。
1.5 ls 常用组合速查
| 命令 | 效果 | 使用场景 |
|---|---|---|
ls -la |
全部文件长格式 | 最常用,查看所有文件详情 |
ls -lh |
人类可读大小 | 快速判断大文件 |
ls -ltr |
按时间逆序 | 查看最近修改的文件 |
ls -lS |
按大小排序 | 排查磁盘占用 |
ls -R |
递归列出 | 了解目录结构 |
ls -d */ |
仅显示目录 | 只看子目录 |
实验二:mkdir / rm / mv / cp / cat / nl
2.1 知识点概览
┌────────────────────────────────────────────────────────────┐
│ 文件与目录操作六命令 │
├──────────┬─────────┬───────────────────────────────────────┤
│ mkdir │ 创建 │ -p: 递归创建 -m: 指定权限 -v: 详细 │
│ rm │ 删除 │ -r: 递归 -f: 强制 -i: 确认 -v: 详细│
│ mv │ 移动/ │ 同分区内移动=改inode指针(快) │
│ │ 重命名 │ 跨分区移动=复制+删除(慢) │
│ cp │ 复制 │ -r: 递归 -p: 保留属性 -u: 增量 │
│ cat │ 查看 │ -n: 所有行号 -b: 非空行号 │
│ │ 合并 │ -s: 压缩连续空行 │
│ nl │ 行号 │ -b a/t: 所有/非空 -n ln/rn: 对齐 │
└──────────┴─────────┴───────────────────────────────────────┘
2.2 mkdir --- 创建目录
bash
# 递归创建多层目录(-p 不会因中间目录不存在而报错)
$ mkdir -p a/b/c/d
$ ls -R a
a:
b
a/b:
c
a/b/c:
d
a/b/c/d:
# 创建时指定权限
$ mkdir -m 755 public_dir
$ ls -ld public_dir
drwxr-xr-x 2 root root 4096 Jun 15 22:15 public_dir
| 选项 | 含义 | 示例 |
|---|---|---|
-p |
创建父目录,已存在不报错 | mkdir -p /var/log/myapp/2026/06 |
-m |
指定权限模式(chmod风格) | mkdir -m 755 public |
-v |
显示创建过程 | mkdir -v dir1 dir2 |
2.3 rm --- 删除文件/目录
bash
# 交互式删除(-i 每次确认)
$ touch delete_me.txt
$ rm -iv delete_me.txt
rm: remove regular empty file 'delete_me.txt'? removed 'delete_me.txt'
# 递归删除目录树(-r 递归,-v 详细)
$ mkdir -p test_rm/sub && touch test_rm/sub/file.txt
$ rm -rv test_rm
removed 'test_rm/sub/file.txt'
removed directory 'test_rm/sub'
removed directory 'test_rm'
| 选项 | 含义 | ⚠️ 风险 |
|---|---|---|
-r |
递归删除目录及内容 | 高危!删除前用 ls -R 确认 |
-f |
强制删除,不提示 | 极高危! rm -rf / 会毁系统 |
-i |
逐个确认 | 建议设置别名 alias rm='rm -i' |
-v |
显示删除过程 | 便于审计 |
踩坑记录 :
rm -rf *不会删除隐藏文件(.开头),需用rm -rf .*或rm -rf * .*。
2.4 mv --- 移动/重命名
bash
# 重命名(同一目录下移动=改名)
$ touch oldname.txt
$ mv oldname.txt newname.txt
$ ls *.txt
newname.txt
# 移动到子目录
$ mkdir dest_dir
$ mv newname.txt dest_dir/
$ ls dest_dir/
newname.txt
原理 :同一文件系统内,
mv只修改目录条目(dirent)中的文件名指针,不复制数据块。因此即使移动 GB 级文件也是瞬间完成。
2.5 cp --- 复制文件/目录
bash
# 基本复制
$ echo "hello copy" > source.txt
$ cp source.txt copy1.txt
$ ls -l source.txt copy1.txt
-rw-r--r-- 1 root root 11 Jun 15 22:15 copy1.txt
-rw-r--r-- 1 root root 11 Jun 15 22:15 source.txt
# 递归复制目录
$ mkdir src_dir && touch src_dir/a.txt src_dir/b.txt
$ cp -r src_dir dest_copy
$ ls -R dest_copy
dest_copy:
a.txt b.txt
# 保留源文件属性(-p = preserve)
$ cp -p source.txt copy_preserve.txt
$ ls -l source.txt copy_preserve.txt
-rw-r--r-- 1 root root 11 Jun 15 22:15 copy_preserve.txt
-rw-r--r-- 1 root root 11 Jun 15 22:15 source.txt
# 增量复制(-u = update,源更新时才复制)
$ echo "newer" > source.txt
$ cp -uv source.txt copy1.txt
'source.txt' -> 'copy1.txt'
| 选项 | 含义 | 典型场景 |
|---|---|---|
-r |
递归复制目录 | cp -r project/ backup/ |
-p |
保留权限/时间戳/所有者 | 备份时保持元数据 |
-u |
仅当源比目标新时复制 | 增量备份 |
-a |
归档模式(-dR --preserve=all) |
完整备份 |
-v |
显示复制过程 | 大量文件时看进度 |
2.6 cat --- 查看与合并文件
bash
# 查看文件内容
$ echo "newer" > source.txt
$ cat source.txt
newer
# -n 显示所有行号
$ printf "line1\nline2\nline3" > numbered.txt
$ cat -n numbered.txt
1 line1
2 line2
3 line3
# -b 仅非空行加行号
$ printf "line1\n\nline3" > with_blank.txt
$ cat -b with_blank.txt
1 line1
2 line3
# -s 压缩连续空行(Squeeze)
$ cat -s with_blank.txt
line1
line3
# 合并多个文件
$ echo "file A" > fa.txt && echo "file B" > fb.txt
$ cat fa.txt fb.txt > merged.txt
$ cat merged.txt
file A
file B
| 选项 | 含义 | 备注 |
|---|---|---|
-n |
所有行加行号(含空行) | 从1开始 |
-b |
仅非空行加行号 | 与 -n 互斥 |
-s |
压缩连续空行为一行 | 清理冗余空行 |
-A |
显示所有控制字符 | $ 表示行尾,^I 表示Tab |
-T |
Tab 显示为 ^I |
区分Tab和空格 |
2.7 nl --- 行号工具(比 cat -n 更灵活)
bash
# 基本用法(等同 cat -n)
$ nl numbered.txt
1 line1
2 line2
3 line3
# -b a 所有行都编号
$ nl -b a with_blank.txt
1 line1
2
3 line3
# -b t 仅非空行编号(默认行为)
$ nl -b t with_blank.txt
1 line1
2 line3
# -n ln 左对齐编号
$ nl -n ln numbered.txt
1 line1
2 line2
3 line3
# -n rn 右对齐编号(默认)
$ nl -n rn numbered.txt
1 line1
2 line2
3 line3
| 选项 | 含义 |
|---|---|
-b a |
所有行编号 |
-b t |
仅非空行编号(默认) |
-n ln |
编号左对齐 |
-n rn |
编号右对齐(默认) |
-n rz |
编号右对齐且补零 |
实验三:more / less / head / tail
3.1 知识点概览
┌───────────────────────────────────────────────────────────────┐
│ 文本浏览四命令 │
├──────────┬────────┬──────────────────────────────────────────┤
│ head │ 看前面 │ -n N: 前N行 -n -N: 除最后N行外的全部 │
│ │ │ -c N: 前N字节 │
├──────────┼────────┼──────────────────────────────────────────┤
│ tail │ 看后面 │ -n N: 后N行 -n +N: 从第N行开始 │
│ │ │ -f: 实时跟踪(日志监控核心) │
├──────────┼────────┼──────────────────────────────────────────┤
│ more │ 分页 │ 早期分页器,只能向下翻 │
├──────────┼────────┼──────────────────────────────────────────┤
│ less │ 分页+ │ 现代分页器,支持前后翻页、搜索高亮 │
│ │ │ 快捷键: j/k上下 f/b翻页 /搜索 q退出 │
└──────────┴────────┴──────────────────────────────────────────┘
首先创建50行测试文件:
bash
$ for i in $(seq 1 50); do echo "Line $i: This is a test line for pagination commands demonstration"; done > longfile.txt
$ wc -l longfile.txt
50 longfile.txt
3.2 head --- 查看文件头部
bash
# 默认显示前10行
$ head longfile.txt
Line 1: This is a test line for pagination commands demonstration
Line 2: This is a test line for pagination commands demonstration
Line 3: This is a test line for pagination commands demonstration
Line 4: This is a test line for pagination commands demonstration
Line 5: This is a test line for pagination commands demonstration
Line 6: This is a test line for pagination commands demonstration
Line 7: This is a test line for pagination commands demonstration
Line 8: This is a test line for pagination commands demonstration
Line 9: This is a test line for pagination commands demonstration
Line 10: This is a test line for pagination commands demonstration
# 显示前3行
$ head -n 3 longfile.txt
Line 1: This is a test line for pagination commands demonstration
Line 2: This is a test line for pagination commands demonstration
Line 3: This is a test line for pagination commands demonstration
# 截取前50字节
$ head -c 50 longfile.txt
Line 1: This is a test line for pagination command
# 显示除了最后5行之外的全部(共50行,显示1~45行)
$ head -n 45 longfile.txt | tail -3
Line 43: This is a test line for pagination commands demonstration
Line 44: This is a test line for pagination commands demonstration
Line 45: This is a test line for pagination commands demonstration
3.3 tail --- 查看文件尾部
bash
# 默认后10行
$ tail longfile.txt
Line 41: This is a test line for pagination commands demonstration
Line 42: This is a test line for pagination commands demonstration
...
Line 50: This is a test line for pagination commands demonstration
# 最后3行
$ tail -n 3 longfile.txt
Line 48: This is a test line for pagination commands demonstration
Line 49: This is a test line for pagination commands demonstration
Line 50: This is a test line for pagination commands demonstration
# 从第46行开始到末尾
$ tail -n +46 longfile.txt
Line 46: This is a test line for pagination commands demonstration
Line 47: This is a test line for pagination commands demonstration
Line 48: This is a test line for pagination commands demonstration
Line 49: This is a test line for pagination commands demonstration
Line 50: This is a test line for pagination commands demonstration
# 截取最后50字节
$ tail -c 50 longfile.txt
a test line for pagination commands demonstration
tail -f 实时监控 :
tail -f /var/log/syslog--- 文件被追加时自动显示新内容,按Ctrl+C退出。运维最常用命令之一。
3.4 more --- 分页浏览(早期工具)
快捷键:
Space → 下一页
b → 上一页
Enter → 下一行
q → 退出
/pattern → 搜索
= → 显示当前行号
3.5 less --- 现代分页器
快捷键(比 more 强大得多):
j/k → 上/下一行
f/b → 前/后翻页
G/g → 文件尾/头
/pattern → 向下搜索
?pattern → 向上搜索
n/N → 下一个/上一个搜索结果
q → 退出
-N → 显示行号
-S → 不折行显示
重要 :
less是 Linux 哲学 "less is more" 的体现 --- 比more更强大。它不会一次性读取整个文件到内存,大文件也能流畅浏览。
3.6 head / tail 日志监控典型组合
bash
# 实时监控日志(最常用)
tail -f /var/log/syslog
# 查看最近100行中的错误
tail -n 100 /var/log/syslog | grep -i error
# 查看文件第11-20行(head+tail组合)
head -n 20 file.txt | tail -n 10
# 截取第100行到末尾
tail -n +100 file.txt
实验四:which / whereis / locate
4.1 知识点概览
┌───────────────────────────────────────────────────────────────┐
│ 命令定位三工具 │
├──────────┬──────────┬─────────────────────────────────────────┤
│ which │ PATH搜索 │ 查找可执行文件的完整路径 │
│ │ │ 仅对PATH中的外部命令有效 │
│ │ │ 内建命令/别名 用 type 替代 │
├──────────┼──────────┼─────────────────────────────────────────┤
│ whereis │ 标准位置 │ 查找二进制+手册+源码 │
│ │ │ 搜索范围固定: /bin,/usr/bin,/usr/man ... │
├──────────┼──────────┼─────────────────────────────────────────┤
│ locate │ 全盘搜索 │ 基于数据库索引,速度极快 │
│ │ │ 需要 updatedb 先构建索引 │
│ │ │ 本机未安装(mlocate包) │
└──────────┴──────────┴─────────────────────────────────────────┘
4.2 which --- 查找 PATH 中的可执行文件
bash
$ which python3
/usr/bin/python3
$ which git
/usr/bin/git
$ which vim curl ls cp
/usr/bin/vim
/usr/bin/curl
/usr/bin/ls
/usr/bin/cp
# -a 显示所有匹配(PATH 中可能有多个同名文件)
$ which -a python3
/usr/bin/python3
/bin/python3
# 内建命令 which 无法定位
$ which cd
$ which echo
/usr/bin/echo ← 该系统有 echo 的外部版本
$ which pwd
/usr/bin/pwd ← 该系统有 pwd 的外部版本
注意 :
which cd无输出 →cd是 shell 内建命令。用type更准确:
bash
$ type cd
cd is a shell builtin
$ type echo
echo is a shell builtin
$ type ls
ls is /usr/bin/ls
$ type git
git is /usr/bin/git
4.3 whereis --- 查找二进制+手册+源码
bash
$ whereis python3
python3: /usr/bin/python3 /usr/lib/python3 /etc/python3 /usr/share/python3 /usr/share/man/man1/python3.1.gz
$ whereis git
git: /usr/bin/git /usr/share/man/man1/git.1.gz
$ whereis bash
bash: /usr/bin/bash /usr/share/man/man1/bash.1.gz
# 仅查二进制 (-b)
$ whereis -b python3
python3: /usr/bin/python3 /usr/lib/python3 /etc/python3 /usr/share/python3
# 仅查手册 (-m)
$ whereis -m python3
python3: /usr/share/man/man1/python3.1.gz
# 仅查源码 (-s)
$ whereis -s python3
python3:
| 选项 | 含义 |
|---|---|
-b |
只搜索二进制文件 |
-m |
只搜索手册页 |
-s |
只搜索源码文件 |
4.4 locate --- 全盘文件名搜索(需要索引)
bash
# 本机未安装 mlocate
$ locate --version
bash: locate: command not found
# 安装方式
$ apt-get install -y mlocate
$ updatedb # 构建索引数据库
$ locate passwd | head -5
# ... 搜索结果
4.5 三工具对比
| 维度 | which | whereis | locate |
|---|---|---|---|
| 搜索范围 | PATH环境变量 | 标准系统目录 | 全盘(由updatedb索引) |
| 搜索内容 | 可执行文件 | 二进制+手册+源码 | 所有文件名 |
| 速度 | 极快 | 快 | 极快(查数据库) |
| 实时性 | 实时 | 实时 | 非实时(需updatedb更新) |
| 内建命令 | 不支持 | 不支持 | 不支持 |
| 典型场景 | 确认用的是哪个版本 | 查手册位置 | 忘记文件放哪了 |
实验五:find / xargs
5.1 知识点概览
┌──────────────────────────────────────────────────────────────┐
│ find --- Linux 最强文件搜索工具 │
├──────────────┬───────────────────────────────────────────────┤
│ 搜索条件 │ -name -type -size -mtime -perm -user -group │
│ 逻辑运算 │ -a(与) -o(或) -not/!(取反) │
│ 执行动作 │ -exec -print -delete -ok │
│ 深度控制 │ -maxdepth -mindepth │
├──────────────┼───────────────────────────────────────────────┤
│ xargs │ 将标准输入转为命令行参数 │
│ │ -n: 每批参数数量 -I: 占位符替换 │
│ │ -p: 执行前确认 -0: NULL分隔(防空格问题) │
└──────────────┴───────────────────────────────────────────────┘
首先创建测试文件结构(Java项目模拟):
bash
$ mkdir -p src/main/java/com/example src/test/java/com/example src/main/resources logs/2026/06
$ touch src/main/java/com/example/App.java src/main/java/com/example/Utils.java
$ touch src/test/java/com/example/AppTest.java src/main/resources/application.yml
$ touch logs/2026/06/app.log logs/2026/06/error.log .gitignore README.md
$ echo "Hello World" > src/main/resources/application.yml
$ echo "ERROR: something wrong" > logs/2026/06/error.log
$ echo "INFO: app started" > logs/2026/06/app.log
5.2 find 按名称查找
bash
$ find . -name "*.java"
./src/test/java/com/example/AppTest.java
./src/main/java/com/example/App.java
./src/main/java/com/example/Utils.java
5.3 find 按类型查找
bash
$ find . -type d -name "example"
./src/test/java/com/example
./src/main/java/com/example
| 类型字符 | 含义 |
|---|---|
f |
普通文件(regular file) |
d |
目录(directory) |
l |
符号链接(symbolic link) |
b |
块设备(block device) |
c |
字符设备(character device) |
s |
套接字(socket) |
p |
命名管道(FIFO) |
5.4 find 按大小查找
bash
$ find . -type f -size +0c
./src/main/resources/application.yml
./logs/2026/06/error.log
./logs/2026/06/app.log
大小单位 :
c=字节,k=KB,M=MB,G=GB
+= 大于,-= 小于,无符号 = 精确匹配
5.5 find 按时间和权限
bash
# 最近1小时内修改的文件
$ find . -type f -mmin -60 | sort
./.gitignore
./README.md
./logs/2026/06/app.log
./logs/2026/06/error.log
./src/main/java/com/example/App.java
./src/main/java/com/example/Utils.java
./src/main/resources/application.yml
./src/test/java/com/example/AppTest.java
# 按权限查找
$ find . -type f -perm 644
./.gitignore
./README.md
./src/main/java/com/example/App.java
./src/main/java/com/example/Utils.java
./src/main/resources/application.yml
./src/test/java/com/example/AppTest.java
./logs/2026/06/app.log
./logs/2026/06/error.log
| 时间选项 | 含义 | 单位 |
|---|---|---|
-mtime N |
修改时间=N天前 | 天 |
-mmin N |
修改时间=N分钟前 | 分钟 |
-atime N |
访问时间 | 天 |
-ctime N |
状态改变时间 | 天 |
5.6 find 深度控制
bash
$ find . -maxdepth 2 -type d
.
./src
./src/test
./src/main
./logs
./logs/2026
5.7 find 组合条件
bash
# 查找所有 .log 或 .yml 文件(-o = OR)
$ find . \( -name "*.log" -o -name "*.yml" \) | sort
./logs/2026/06/app.log
./logs/2026/06/error.log
./src/main/resources/application.yml
# 取反:查找空文件
$ touch empty_file.txt
$ find . -type f -empty
./.gitignore
./README.md
./src/main/java/com/example/App.java
./src/main/java/com/example/Utils.java
./src/test/java/com/example/AppTest.java
./empty_file.txt
5.8 find 执行命令
bash
# -exec 方式:每个文件独立执行
$ find . -name "*.java" -exec wc -l {} \;
0 ./src/test/java/com/example/AppTest.java
0 ./src/main/java/com/example/App.java
0 ./src/main/java/com/example/Utils.java
5.9 find + xargs 组合(更高效)
bash
# xargs 方式:批量传递参数,少次调用
$ find . -name "*.java" | xargs wc -l
0 ./src/test/java/com/example/AppTest.java
0 ./src/main/java/com/example/App.java
0 ./src/main/java/com/example/Utils.java
0 total
-execvsxargs:-exec每个文件调一次命令(慢),xargs批量调用(快)。但文件名含空格时xargs可能出错,用xargs -0+find -print0解决。
5.10 xargs 其他用法
bash
# -n 2:每次传2个参数
$ echo "one two three four five" | xargs -n 2 echo
one two
three four
five
# -I {}:占位符替换
$ find . -name "*.java" | xargs -I {} echo "Processing: {}"
Processing: ./src/test/java/com/example/AppTest.java
Processing: ./src/main/java/com/example/App.java
Processing: ./src/main/java/com/example/Utils.java
# 删除文件
$ find . -name "empty_file.txt" | xargs rm -v
removed './empty_file.txt'
5.11 find 常用实战组合
bash
# 查找并删除30天前的日志
find /var/log -name "*.log" -mtime +30 -exec rm {} \;
# 查找大文件(>100MB)
find / -type f -size +100M -exec ls -lh {} \;
# 查找空目录并删除
find . -type d -empty -delete
# 批量修改文件权限
find . -name "*.sh" -exec chmod +x {} \;
# 查找最近修改的5个文件
find . -type f -printf '%T@ %p\n' | sort -rn | head -5
实验六:wc / grep / 正则表达式
6.1 知识点概览
┌──────────────────────────────────────────────────────────────┐
│ 文本统计 + 搜索 + 正则 │
├──────────┬─────────┬─────────────────────────────────────────┤
│ wc │ 统计 │ -l:行 -c:字节 -m:字符 -w:单词 -L:最长行 │
├──────────┼─────────┼─────────────────────────────────────────┤
│ grep │ 搜索 │ -i:忽略大小写 -v:反向 -n:行号 │
│ │ │ -c:计数 -w:全词 -r:递归 -l:文件名 │
│ │ │ -A/B/C:上下文 -E:扩展正则 -o:仅匹配 │
├──────────┼─────────┼─────────────────────────────────────────┤
│ 正则 │ 模式 │ ^行首 $行尾 .任意 []字符类 *0~N次 │
│ │ │ + 1~N次 ? 0/1次 {N}精确 {N,M}范围 │
└──────────┴─────────┴─────────────────────────────────────────┘
创建测试数据:
bash
$ printf "apple\nbanana\nApple\nBANANA\nAPPLE\napricot\navocado\nblackberry\nblueberry\ncranberry" > fruits.txt
$ printf "user001:alice:admin\nuser002:bob:user\nuser003:charlie:admin\nuser004:david:user\nuser005:eve:admin\nuser006:frank:guest" > users.txt
$ printf "192.168.1.1 - GET /index.html 200\n192.168.1.2 - POST /api/login 401\n10.0.0.1 - GET /api/users 200\n192.168.1.1 - GET /images/logo.png 304\n10.0.0.2 - DELETE /api/session 500\n192.168.1.3 - PUT /api/profile 200\n10.0.0.1 - GET /api/data 200\n192.168.1.4 - POST /api/upload 413" > access.log
6.2 wc --- 文本统计
bash
# 行数统计
$ wc -l fruits.txt users.txt
9 fruits.txt
5 users.txt
14 total
# 多维度统计
$ wc -c fruits.txt # 字节数
78 fruits.txt
$ wc -m fruits.txt # 字符数
78 fruits.txt
$ wc -w fruits.txt # 单词数
10 fruits.txt
$ wc -L fruits.txt # 最长行字符数
10 fruits.txt
| 选项 | 含义 | 示例 |
|---|---|---|
-l |
行数 | wc -l file.txt |
-c |
字节数 | wc -c file.txt |
-m |
字符数(多字节字符正确计数) | wc -m file.txt |
-w |
单词数 | wc -w file.txt |
-L |
最长行的字符数 | wc -L file.txt |
6.3 grep --- 文本搜索
bash
# 基本搜索(区分大小写)
$ grep "apple" fruits.txt
apple
# -i 忽略大小写
$ grep -i "apple" fruits.txt
apple
Apple
APPLE
# -v 反向匹配(排除)
$ grep -v "berry" fruits.txt
apple
banana
Apple
BANANA
APPLE
apricot
avocado
# -c 计数
$ grep -c "admin" users.txt
3
# -w 全词匹配(不是子串)
$ grep -w "apple" fruits.txt
apple
$ grep -w "app" fruits.txt
(no exact match)
6.4 grep 上下文控制
bash
# -n 显示行号
$ grep -n "GET" access.log
1:192.168.1.1 - GET /index.html 200
3:10.0.0.1 - GET /api/users 200
4:192.168.1.1 - GET /images/logo.png 304
7:10.0.0.1 - GET /api/data 200
# -A 2:显示匹配行及之后2行
$ grep -A 2 "192.168.1.1" access.log
192.168.1.1 - GET /index.html 200
192.168.1.2 - POST /api/login 401
10.0.0.1 - GET /api/users 200
192.168.1.1 - GET /images/logo.png 304
10.0.0.2 - DELETE /api/session 500
192.168.1.3 - PUT /api/profile 200
# -B 2:显示匹配行及之前2行
$ grep -B 2 "500" access.log
10.0.0.1 - GET /api/users 200
192.168.1.1 - GET /images/logo.png 304
10.0.0.2 - DELETE /api/session 500
# -C 1:显示匹配行前后各1行
$ grep -C 1 "401" access.log
192.168.1.1 - GET /index.html 200
192.168.1.2 - POST /api/login 401
10.0.0.1 - GET /api/users 200
6.5 grep 递归与文件搜索
bash
# -r 递归搜索目录
$ grep -r "ERROR" /tmp/cmd-lab-05/
/tmp/cmd-lab-05/logs/2026/06/error.log:ERROR: something wrong
# -l 仅显示含匹配的文件名
$ grep -rl "Hello" /tmp/cmd-lab-05/
/tmp/cmd-lab-05/src/main/resources/application.yml
6.6 grep 正则表达式
bash
# 行尾锚定:以 200 结尾的行
$ grep -E "200$" access.log
192.168.1.1 - GET /index.html 200
10.0.0.1 - GET /api/users 200
192.168.1.3 - PUT /api/profile 200
10.0.0.1 - GET /api/data 200
# 行首锚定:以 192 开头的行(内网IP)
$ grep "^192" access.log
192.168.1.1 - GET /index.html 200
192.168.1.2 - POST /api/login 401
192.168.1.1 - GET /images/logo.png 304
192.168.1.3 - PUT /api/profile 200
192.168.1.4 - POST /api/upload 413
# IP 地址匹配
$ grep -E "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" access.log | head -3
192.168.1.1 - GET /index.html 200
192.168.1.2 - POST /api/login 401
10.0.0.1 - GET /api/users 200
6.7 grep 管道组合(最常用)
bash
# 统计成功(200)且为GET请求的数量
$ grep "200" access.log | grep "GET" | wc -l
3
6.8 正则表达式速查
┌─────────────────────────────────────────────────────┐
│ 基础正则 (BRE --- grep 默认) │
│ ^ 行首锚定 $ 行尾锚定 │
│ . 任意单字符 * 前字符0~N次 │
│ [] 字符类 [^] 否定字符类 │
│ \ 转义符 \< \> 词边界 │
├─────────────────────────────────────────────────────┤
│ 扩展正则 (ERE --- grep -E / egrep) │
│ + 前字符1~N次 ? 前字符0/1次 │
│ {N} 精确N次 {N,} 至少N次 │
│ {N,M} N~M次 | 或(alternation) │
│ () 分组 \1 反向引用 │
└─────────────────────────────────────────────────────┘
实验七:cut / paste / tr
7.1 知识点概览
┌──────────────────────────────────────────────────────────────┐
│ 列处理 + 合并 + 字符转换 │
├──────────┬─────────┬─────────────────────────────────────────┤
│ cut │ 列截取 │ -f:按字段(需-d分隔符) -c:按字符位置 │
│ │ │ -b:按字节位置 │
├──────────┼─────────┼─────────────────────────────────────────┤
│ paste │ 行合并 │ 横向:多文件逐行拼接 │
│ │ │ -s: 纵向串行化(多行合并为一行) │
│ │ │ -d: 自定义分隔符(默认Tab) │
├──────────┼─────────┼─────────────────────────────────────────┤
│ tr │ 字符转换│ 一对一替换 -d:删除 -s:压缩重复 │
│ │ │ -c:补集操作 │
│ │ │ [:upper:] [:lower:] [:digit:] 等字符类 │
└──────────┴─────────┴─────────────────────────────────────────┘
创建测试数据:
bash
$ printf "ID\tName\tAge\tCity\n1\tAlice\t28\tBeijing\n2\tBob\t35\tShanghai\n3\tCarol\t22\tShenzhen\n4\tDavid\t30\tHangzhou\n5\tEve\t26\tChengdu" > people.tsv
$ cat people.tsv
ID Name Age City
1 Alice 28 Beijing
2 Bob 35 Shanghai
3 Carol 22 Shenzhen
4 David 30 Hangzhou
5 Eve 26 Chengdu
7.2 cut --- 列截取
bash
# 按字段截取(-f 字段号,-d 分隔符默认Tab)
$ cut -f 2,4 people.tsv
Name City
Alice Beijing
Bob Shanghai
Carol Shenzhen
David Hangzhou
Eve Chengdu
# 处理 /etc/passwd(以 : 分隔)
$ cut -d: -f1,7 /etc/passwd | head -5
root:/bin/bash
daemon:/usr/sbin/nologin
bin:/usr/sbin/nologin
sys:/usr/sbin/nologin
sync:/bin/sync
# 按字符位置截取
$ echo "ABCDEFGHIJ" | cut -c 1-5
ABCDE
$ echo "ABCDEFGHIJ" | cut -c 1,3,5,7,9
ACEGI
7.3 paste --- 行合并
bash
$ printf "1\n2\n3\n4\n5" > ids.txt
$ printf "Alice\nBob\nCarol\nDavid\nEve" > names.txt
# 基本:逐行合并(Tab分隔)
$ paste ids.txt names.txt
1 Alice
2 Bob
3 Carol
4 David
5 Eve
# 自定义分隔符
$ paste -d: ids.txt names.txt
1:Alice
2:Bob
3:Carol
4:David
5:Eve
# -s 串行化:多行合并为一行
$ paste -s -d, ids.txt
1,2,3,4,5
7.4 tr --- 字符转换
bash
# 大小写转换
$ echo "Hello World" | tr "a-z" "A-Z"
HELLO WORLD
$ echo "Hello World" | tr "[:upper:]" "[:lower:]"
hello world
# 删除字符 (-d)
$ echo "Hello World 123" | tr -d " "
HelloWorld123
# 压缩重复字符 (-s)
$ echo "Hello World !!!" | tr -s " "
Hello World !!!
# 字符集替换
$ echo "abc123def456" | tr "0-9" "A-J"
abcBCDdefFGH
# 补集操作 (-c):保留数字,删除其他
$ echo "abc123def456" | tr -cd "0-9"
123456
7.5 cut / paste / tr 组合实战
bash
# 日志清洗:Tab→竖线 + 大写→小写
$ printf "ERROR\t2026-06-15\tServer Down!" | tr "\t" "|" | tr "[:upper:]" "[:lower:]"
error|2026-06-15|server down!
# 提取用户名并转大写
$ cut -d: -f1 /etc/passwd | tr "a-z" "A-Z" | head -5
ROOT
DAEMON
BIN
SYS
SYNC
# 用户名+Shell 并排
$ paste <(cut -d: -f1 /etc/passwd | head -5) <(cut -d: -f7 /etc/passwd | head -5)
root /bin/bash
daemon /usr/sbin/nologin
bin /usr/sbin/nologin
sys /usr/sbin/nologin
sync /bin/sync
<(command)进程替换:将命令输出当作临时文件使用,是 bash 高级特性。
实验八:sort / uniq / join
8.1 知识点概览
┌──────────────────────────────────────────────────────────────┐
│ 排序 + 去重 + 连接 │
├──────────┬─────────┬─────────────────────────────────────────┤
│ sort │ 排序 │ 默认按ASCII字典序 │
│ │ │ -n:数值 -h:人类可读 -M:月份 -r:逆序 │
│ │ │ -k:按列 -t:分隔符 -u:去重输出 │
├──────────┼─────────┼─────────────────────────────────────────┤
│ uniq │ 去重 │ -c:计数 -d:仅重复行 -u:仅唯一行 │
│ │ │ ⚠️ 只能处理相邻重复行,通常先sort再uniq │
├──────────┼─────────┼─────────────────────────────────────────┤
│ join │ 连接 │ 类似SQL JOIN,按公共字段合并两个文件 │
│ │ │ -a:显示未匹配 -v:仅未匹配 -t:分隔符 │
└──────────┴─────────┴─────────────────────────────────────────┘
8.2 sort --- 排序
bash
# 默认按ASCII字典序(大写字母排在小写之前!)
$ printf "orange\napple\nbanana\nApple\nOrange" | sort
apple
Apple
banana
orange
Orange
# -r 逆序
$ printf "orange\napple\nbanana\nApple\nOrange" | sort -r
Orange
orange
banana
Apple
apple
ASCII 排序规则 :大写字母(A-Z: 65-90)的 ASCII 码值 小于 小写字母(a-z: 97-122),所以
Apple排在apple之前。
bash
# -n 数值排序
$ printf "10\n2\n100\n5\n1\n20" | sort -n
1
2
5
10
20
100
# -h 人类可读大小排序(识别 K/M/G 单位)
$ printf "1K\n10M\n2G\n100M\n1G" | sort -h
1K
10M
100M
1G
2G
# -k 按列排序
$ printf "Alice 500\nBob 300\nCarol 800\nDavid 200" | sort -k2 -n
David 200
Bob 300
Alice 500
Carol 800
# -t 指定分隔符 + -k 按指定列
$ printf "1:Alice:500\n2:Bob:300\n3:Carol:800\n4:David:200" | sort -t: -k3 -n
4:David:200
2:Bob:300
1:Alice:500
3:Carol:800
# -u 去重输出
$ printf "apple\nbanana\napple\ncherry\nbanana" | sort -u
apple
banana
cherry
# -M 月份排序
$ printf "Mar\nJan\nFeb\nApr\nDec" | sort -M
Jan
Feb
Mar
Apr
Dec
8.3 uniq --- 去重与统计
bash
# 基本去重(仅合并相邻重复行)
$ printf "apple\napple\nbanana\nbanana\nbanana\ncherry" | uniq
apple
banana
cherry
# -c 计数(最重要的选项!)
$ printf "apple\napple\nbanana\nbanana\nbanana\ncherry\napple" | sort | uniq -c | sort -rn
3 banana
3 apple
1 cherry
# -d 仅显示重复行
$ printf "apple\napple\nbanana\ncherry\nbanana" | sort | uniq -d
apple
banana
# -u 仅显示唯一行
$ printf "apple\napple\nbanana\ncherry\nbanana" | sort | uniq -u
cherry
8.4 sort+uniq 实战:HTTP方法频率统计
bash
$ printf "GET\nPOST\nGET\nDELETE\nGET\nPOST\nPUT\nGET" | sort | uniq -c | sort -rn
4 GET
2 POST
1 PUT
1 DELETE
这是运维最常用的分析模式 :
sort | uniq -c | sort -rn--- 排序→计数→按频率降序。
8.5 join --- 类SQL连接
需要两个文件的关键字段已排序。
bash
$ printf "1 Alice\n2 Bob\n3 Carol" > employees.txt
$ printf "1 Engineer\n2 Designer\n3 Manager" > roles.txt
# 基本连接(默认按第一个字段)
$ join employees.txt roles.txt
1 Alice Engineer
2 Bob Designer
3 Carol Manager
# 指定分隔符
$ printf "1:Alice:50000\n2:Bob:45000\n3:Carol:60000" > emp2.txt
$ printf "1:Engineering\n2:Design\n3:Management" > dept.txt
$ join -t: emp2.txt dept.txt
1:Alice:50000:Engineering
2:Bob:45000:Design
3:Carol:60000:Management
# 左连接(-a 1:显示file1中未匹配的行)
$ printf "1 Alice\n2 Bob\n3 Carol\n4 David" > all_emp.txt
$ printf "1 Engineer\n3 Manager" > some_roles.txt
$ join -a 1 all_emp.txt some_roles.txt
1 Alice Engineer
2 Bob
3 Carol Manager
4 David
# 仅显示未匹配行(-v 1:file1中有但file2中没有的)
$ join -v 1 all_emp.txt some_roles.txt
2 Bob
4 David
实验九:comm / diff / patch
9.1 知识点概览
┌──────────────────────────────────────────────────────────────┐
│ 文件比较三工具 │
├──────────┬─────────┬─────────────────────────────────────────┤
│ comm │ 逐行比较│ 输出3列:1=仅file1 2=仅file2 3=共有 │
│ │ │ -1 -2 -3 隐藏对应列 │
│ │ │ ⚠️ 要求两个文件已排序 │
├──────────┼─────────┼─────────────────────────────────────────┤
│ diff │ 差异 │ 逐行比较,输出差异 │
│ │ │ -u: unified格式(最常用) │
│ │ │ -c: context格式 -y: 并排显示 │
│ │ │ -i: 忽略大小写 -w: 忽略空白 │
│ │ │ -r: 递归目录比较 │
├──────────┼─────────┼─────────────────────────────────────────┤
│ patch │ 打补丁 │ 将 diff 输出应用到文件 │
│ │ │ patch < changes.patch 正向应用 │
│ │ │ patch -R < changes.patch 反向撤销 │
└──────────┴─────────┴─────────────────────────────────────────┘
创建测试文件:
bash
$ printf "apple\nbanana\ncherry\ndate\nelderberry" > file1.txt
$ printf "apple\nbanana\ncranberry\ndate\nfig" > file2.txt
bash
$ cat file1.txt
apple
banana
cherry
date
elderberry
$ cat file2.txt
apple
banana
cranberry
date
fig
9.2 comm --- 逐行比较
bash
# 三列输出:Tab缩进 = 仅file1 | Tab = 仅file2 | 无缩进 = 共有
$ comm file1.txt file2.txt
apple
banana
cherry
cranberry
date
elderberry
fig
| 列 | 缩进 | 含义 |
|---|---|---|
| 第1列 | 无 | 仅在 file1 中存在 |
| 第2列 | 1个Tab | 仅在 file2 中存在 |
| 第3列 | 2个Tab | 两个文件共有 |
bash
# 隐藏第1列(仅显示file2独有+共有)
$ comm -1 file1.txt file2.txt
apple
banana
cranberry
date
fig
# 隐藏第3列(仅显示各自独有的行)
$ comm -3 file1.txt file2.txt
cherry
cranberry
elderberry
fig
# -12 仅显示共有行(交集)
$ comm -12 file1.txt file2.txt
apple
banana
date
9.3 diff --- 差异对比
bash
# 基本输出(ed风格指令)
$ diff file1.txt file2.txt
3c3
< cherry
---
> cranberry
5c5
< elderberry
---
> fig
输出解读 :3c3 = 第3行 change 为第3行;< = file1(旧),> = file2(新)。
bash
# unified 格式(-u,最推荐)
$ diff -u file1.txt file2.txt
--- file1.txt 2026-06-15 22:24:42.317639317 +0800
+++ file2.txt 2026-06-15 22:24:42.317639317 +0800
@@ -1,5 +1,5 @@
apple
banana
-cherry
+cranberry
date
-elderberry
+fig
unified 格式解读 :
---旧文件,+++新文件;@@ -1,5 +1,5 @@表示旧文件1-5行→新文件1-5行;-删除行,+新增行。
bash
# context 格式(-c)
$ diff -c file1.txt file2.txt
*** file1.txt 2026-06-15 22:24:42.317639317 +0800
--- file2.txt 2026-06-15 22:24:42.317639317 +0800
***************
*** 1,5 ****
apple
banana
! cherry
date
! elderberry
--- 1,5 ----
apple
banana
! cranberry
date
! fig
bash
# 并排显示(-y,直观对比)
$ diff -y file1.txt file2.txt
apple apple
banana banana
cherry | cranberry
date date
elderberry | fig
9.4 diff 选项
bash
# -i 忽略大小写(无输出 = 内容相同)
$ echo "HELLO" > cap.txt && echo "hello" > lower.txt
$ diff -i cap.txt lower.txt
(no output = identical)
# -w 忽略空白差异
$ echo "hello world" > with_spaces.txt && echo "hello world" > no_spaces.txt
$ diff -w with_spaces.txt no_spaces.txt
(no output = identical)
# -r 递归比较目录
$ mkdir -p dir_a dir_b
$ cp file1.txt dir_a/ && cp file2.txt dir_b/file1.txt
$ diff -r dir_a dir_b
diff -r dir_a/file1.txt dir_b/file1.txt
3c3
< cherry
---
> cranberry
5c5
< elderberry
---
> fig
9.5 patch --- 补丁的应用与撤销
bash
# Step 1: 创建补丁
$ diff -u file1.txt file2.txt > changes.patch
$ cat changes.patch
--- file1.txt 2026-06-15 22:24:42.317639317 +0800
+++ file2.txt 2026-06-15 22:24:42.317639317 +0800
@@ -1,5 +1,5 @@
apple
banana
-cherry
+cranberry
date
-elderberry
+fig
# Step 2: 应用补丁
$ patch file1.txt < changes.patch
patching file file1.txt
# Step 3: 验证 --- file1 已变成 file2 的内容
$ cat file1.txt
apple
banana
cranberry
date
fig
# Step 4: 反向应用(撤销补丁)
$ patch -R file1.txt < changes.patch
patching file file1.txt
$ cat file1.txt
apple
banana
cherry
date
elderberry
patch 典型场景 :开源项目中用
git format-patch生成补丁 → 邮件发给维护者 →git am或patch应用。
实验十:df / du / time
10.1 知识点概览
┌──────────────────────────────────────────────────────────────┐
│ 磁盘 + 性能测量 │
├──────────┬─────────┬─────────────────────────────────────────┤
│ df │ 文件系统│ -h:人类可读 -i:inode -T:文件系统类型 │
│ │ 级别 │ 反映整个分区的使用情况 │
├──────────┼─────────┼─────────────────────────────────────────┤
│ du │ 目录/ │ -sh:汇总+人类可读 -a:所有文件 │
│ │ 文件级 │ --max-depth=N:限制深度 -c:合计 │
│ │ │ 统计目录/文件实际占用空间 │
├──────────┼─────────┼─────────────────────────────────────────┤
│ time │ 计时 │ real:墙上时钟 user:用户态CPU │
│ │ │ sys:内核态CPU │
└──────────┴─────────┴─────────────────────────────────────────┘
10.2 df --- 文件系统磁盘使用
bash
$ df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 341M 1.1M 340M 1% /run
/dev/vda1 40G 3.6G 35G 10% /
tmpfs 1.7G 0 1.7G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 341M 12K 341M 1% /run/user/0
本机信息 :根分区
/dev/vda140G(ext4),已用 3.6G(10%),tmpfs 是内存文件系统。
bash
# -i 查看 inode 使用情况
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
tmpfs 436466 692 435774 1% /run
/dev/vda1 2621440 109166 2512274 5% /
tmpfs 436466 1 436465 1% /dev/shm
tmpfs 436466 3 436463 1% /run/lock
tmpfs 87293 33 87260 1% /run/user/0
# -T 显示文件系统类型
$ df -T
Filesystem Type 1K-blocks Used Available Use% Mounted on
tmpfs tmpfs 349176 1044 348132 1% /run
/dev/vda1 ext4 41169244 3696420 35673984 10% /
tmpfs tmpfs 1745864 0 1745864 0% /dev/shm
tmpfs tmpfs 5120 0 5120 0% /run/lock
tmpfs tmpfs 349172 12 349160 1% /run/user/0
10.3 du --- 目录/文件大小
bash
# 汇总各目录大小
$ du -sh /tmp/cmd-lab-01 /tmp/cmd-lab-02 /tmp/cmd-lab-03
16K /tmp/cmd-lab-01
68K /tmp/cmd-lab-02
8.0K /tmp/cmd-lab-03
# 限制深度查看(类似 tree)
$ du -h --max-depth=1 /tmp/cmd-lab-05
44K /tmp/cmd-lab-05/src
20K /tmp/cmd-lab-05/logs
68K /tmp/cmd-lab-05
# -a 列出所有文件
$ du -a /tmp/cmd-lab-05 | head -10
0 /tmp/cmd-lab-05/README.md
0 /tmp/cmd-lab-05/src/test/java/com/example/AppTest.java
4 /tmp/cmd-lab-05/src/test/java/com/example
8 /tmp/cmd-lab-05/src/test/java/com
12 /tmp/cmd-lab-05/src/test/java
16 /tmp/cmd-lab-05/src/test
4 /tmp/cmd-lab-05/src/main/resources/application.yml
8 /tmp/cmd-lab-05/src/main/resources
0 /tmp/cmd-lab-05/src/main/java/com/example/App.java
0 /tmp/cmd-lab-05/src/main/java/com/example/Utils.java
# -c 显示合计
$ du -shc /tmp/cmd-lab-01 /tmp/cmd-lab-02 /tmp/cmd-lab-03
16K /tmp/cmd-lab-01
68K /tmp/cmd-lab-02
8.0K /tmp/cmd-lab-03
92K total
# 按大小排序各测试目录
$ du -sh /tmp/cmd-lab-*/ 2>/dev/null | sort -rh
68K /tmp/cmd-lab-05/
68K /tmp/cmd-lab-02/
28K /tmp/cmd-lab-08/
16K /tmp/cmd-lab-01/
12K /tmp/cmd-lab-09/
8.0K /tmp/cmd-lab-03/
4.0K /tmp/cmd-lab-10/
4.0K /tmp/cmd-lab-04/
10.4 df vs du 对比
| 维度 | df | du |
|---|---|---|
| 视角 | 文件系统级别 | 目录/文件级别 |
| 数据来源 | 超级块(superblock) | 递归遍历 inode |
| 是否包含已删除但被进程占用的文件 | 包含(deleted但fd未释放) | 不包含 |
| 典型用法 | 监控磁盘整体健康 | 排查哪个目录占用大 |
| 常见差异 | df 显示磁盘满了 |
du 显示还有很多空间 |
经典踩坑 :日志文件被
rm删除但进程持有句柄未释放 →df显示满du显示空 →lsof | grep deleted排查。
10.5 time --- 命令计时
bash
$ time ls -laR /etc > /dev/null
real 0m0.009s
user 0m0.001s
sys 0m0.007s
$ time sleep 0.5
real 0m0.501s
user 0m0.001s
sys 0m0.000s
$ time find /tmp/cmd-lab-05 -name "*.java" > /dev/null
real 0m0.001s
user 0m0.000s
sys 0m0.001s
| 时间类型 | 含义 | sleep 示例解读 |
|---|---|---|
| real | 墙上时钟(实际流逝时间) | 0.501s ≈ 0.5s等待+启动开销 |
| user | 用户态 CPU 时间 | 0.001s(sleep 不需要CPU运算) |
| sys | 内核态 CPU 时间 | 0.000s(几乎无系统调用) |
10.6 文件系统类型对照
| 类型 | 特点 | 适用场景 |
|---|---|---|
| ext4 | Linux 默认,成熟稳定 | 通用(本机使用) |
| xfs | 高性能,支持大文件 | 数据库/大数据 |
| btrfs | COW、快照、压缩 | 现代容器/桌面 |
| tmpfs | 内存文件系统 | 临时文件//tmp//dev/shm |
| overlay | 联合文件系统 | Docker 容器镜像 |
10.7 dd 创建大文件演示
bash
$ dd if=/dev/zero of=testfile bs=1M count=10 2>&1
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00248765 s, 4.2 GB/s
$ ls -lh testfile
-rw-r--r-- 1 root root 10M Jun 15 22:24 testfile
$ du -h testfile
10M testfile
dd 参数 :
if=输入文件,of=输出文件,bs=块大小,count=块数量。/dev/zero提供无限零字节流。
命令速查表
文件目录操作
| 命令 | 核心选项 | 一行示例 |
|---|---|---|
ls |
-la -lh -ltr -R |
ls -ltr --color=auto |
cd |
- .. ~ / |
cd - 回到上次目录 |
pwd |
-P -L |
pwd -P 显示物理路径 |
mkdir |
-p -m -v |
mkdir -p a/b/c |
rm |
-rf -i -v |
rm -rfv old_dir/ |
mv |
-i -v |
mv old new |
cp |
-rp -u -a |
cp -rp src/ dst/ |
cat |
-n -b -s |
cat -n file.txt |
nl |
-b a/t -n ln/rn |
nl -b a file.txt |
文本浏览
| 命令 | 核心选项 | 一行示例 |
|---|---|---|
head |
-n N -c N |
head -n 20 file.txt |
tail |
-n N -f -n +N |
tail -f /var/log/syslog |
more |
分页浏览 | more longfile.txt |
less |
前后翻页/搜索 | less -N longfile.txt |
搜索定位
| 命令 | 核心选项 | 一行示例 |
|---|---|---|
which |
-a |
which python3 |
whereis |
-b -m -s |
whereis -b ls |
locate |
-i -r |
locate passwd |
find |
-name -type -size -mtime -exec |
find . -name '*.log' -mtime +7 -delete |
grep |
-i -v -n -r -E -A/B/C |
grep -rn 'TODO' src/ |
文本处理
| 命令 | 核心选项 | 一行示例 |
|---|---|---|
wc |
-l -c -w -L |
wc -l *.txt |
cut |
-f -d -c |
cut -d: -f1,7 /etc/passwd |
paste |
-s -d |
paste -d: file1 file2 |
tr |
-d -s -c |
tr 'a-z' 'A-Z' < file |
sort |
-n -r -k -t -h |
sort -t: -k3 -n file |
uniq |
-c -d -u |
`sort |
join |
-t -a -v |
join -t: file1 file2 |
comm |
-1 -2 -3 -12 |
comm -12 file1 file2 |
diff |
-u -c -y -r |
diff -u old.txt new.txt |
patch |
< patch -R |
patch < fix.patch |
xargs |
-n -I -0 |
`find . -name '*.tmp' |
系统信息
| 命令 | 核心选项 | 一行示例 |
|---|---|---|
df |
-h -i -T |
df -h / |
du |
-sh -a --max-depth -c |
`du -sh * |
time |
bash内建 | time ls -R /usr/ > /dev/null |
dd |
if= of= bs= count= |
dd if=/dev/zero of=test bs=1M count=10 |
本文档所有命令输出均来自华为云 ECS ecs-b97e-0001 (Ubuntu 24.04 LTS, Linux 6.8.0),于 2026-06-15 真实执行。