← 返回

Linux 基础命令复习手册

首发 2026/07/30 阅读 0 评论 0 更新 2026/07/30

Linux 基础命令复习手册

目标:能独立完成文件操作、内容检索、管道组合和日志查看,并能解释命令背后的工作方式。示例统一使用普通用户提示符 $# 表示 root,复制命令时不要把提示符一起复制。

1. 高频命令总表

任务 首选命令 高频选项/写法
查看目录 ls -l-a-h-t
切换/确认目录 cdpwd cd ..cd -cd ~
创建目录/文件 mkdirtouch mkdir -p
查看文件 catlessheadtail less -Ntail -ftail -F
查看文件信息 filestat stat 文件
复制/移动 cpmv cp -acp -r-i
删除 rmrmdir rm -rrm -i
查找文件 find -name-type-size-mtime
查找命令 typecommand -v type -a
过滤内容 grep -n-i-r-E-v
统计内容 wc -l-w-c-m
排序去重 sortuniq sort -nsort -uuniq -c
提取列 cutawk cut -d: -f1
管道 ` `
重定向 >>>2> 覆盖、追加、重定向错误
同时看并保存 tee `命令
编辑文件 vim iEsc:wq:q!
查帮助 --helpman man 5 passwd

必须认识的目录

目录 主要内容
/ 整棵目录树的根
/home 普通用户家目录
/root root 的家目录,不是根目录 /
/etc 系统和服务配置
/var 经常变化的数据,如日志、缓存、队列
/var/log 常见日志目录
/usr/bin 大量普通命令
/usr/sbin 大量系统管理命令
/tmp 临时文件,可能被系统清理
/opt 可选的第三方软件
/srv 服务对外提供的数据
/dev 设备文件
/proc 内核和进程信息的虚拟文件系统
/sys 设备与内核对象信息的虚拟文件系统

2. 先准备一套统一练习数据

后面的命令都围绕 ~/linux-lab 演示:

console
[mia@linux ~]$ mkdir -p ~/linux-lab/{app,data,logs,backup}

[mia@linux ~]$ cat > ~/linux-lab/data/users.txt <<'EOF'
1001 alice backend active
1002 bob frontend active
1003 carol backend disabled
1004 dave ops active
EOF

[mia@linux ~]$ cat > ~/linux-lab/logs/app.log <<'EOF'
2026-07-29 09:00:01 INFO  server started port=8000
2026-07-29 09:02:16 INFO  GET /posts status=200
2026-07-29 09:03:40 ERROR database timeout request_id=r101
2026-07-29 09:04:03 WARN  slow request cost=1.82s
2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload
EOF

[mia@linux ~]$ printf 'DEBUG=false\nPORT=8000\n' > ~/linux-lab/app/config.env
[mia@linux ~]$ touch ~/linux-lab/app/main.py

查看结构:

console
[mia@linux ~]$ find ~/linux-lab -maxdepth 2 -printf '%P\n' | sort

app
app/config.env
app/main.py
backup
data
data/users.txt
logs
logs/app.log

开头出现的空行代表 ~/linux-lab 本身;这是 find 的正常结果。


3. Linux 目录树与路径

3.1 Linux 只有一棵目录树

Windows 常见 C:\D:\ 多个盘符;Linux 从唯一的根目录 / 开始。其他磁盘和文件系统通常被挂载到这棵树的某个目录。

text
/
├── etc
├── home
│   └── mia
├── usr
├── var
└── ...

3.2 绝对路径与相对路径

路径 起点 示例
绝对路径 根目录 / /home/mia/linux-lab/logs/app.log
相对路径 当前工作目录 logs/app.log
console
[mia@linux ~]$ cd ~/linux-lab
[mia@linux linux-lab]$ pwd
/home/mia/linux-lab

[mia@linux linux-lab]$ cat logs/app.log
2026-07-29 09:00:01 INFO  server started port=8000
...

[mia@linux linux-lab]$ cat /home/mia/linux-lab/logs/app.log
2026-07-29 09:00:01 INFO  server started port=8000
...

3.3 特殊路径

写法 含义
. 当前目录
.. 上一级目录
~ 当前用户家目录
~alice 用户 alice 的家目录
- cd 中表示上一次所在目录
console
[mia@linux linux-lab]$ cd logs
[mia@linux logs]$ cd ..
[mia@linux linux-lab]$ cd -
/home/mia/linux-lab/logs
[mia@linux logs]$ cd
[mia@linux ~]$

cd 不带参数等价于回到当前用户的家目录。

3.4 文件名、隐藏文件与大小写

  • . 开头的名称默认隐藏,例如 .bashrc
  • Linux 文件名通常区分大小写:App.pyapp.py 是两个名称。
  • 扩展名不决定文件本质,file 会根据内容判断类型。
console
[mia@linux ~]$ ls
linux-lab

[mia@linux ~]$ ls -a
.  ..  .bashrc  .ssh  linux-lab

[mia@linux ~]$ file ~/linux-lab/logs/app.log
/home/mia/linux-lab/logs/app.log: ASCII text

4. 命令的基本结构

常见形式:

text
command [options] [arguments]
console
[mia@linux ~]$ ls -lah ~/linux-lab
  • ls:命令;
  • -l-a-h:选项;
  • ~/linux-lab:参数。

短选项常可合并,下面三种通常等价:

console
$ ls -l -a -h
$ ls -lah
$ ls -hal

长选项通常以两个连字符开头:

console
$ ls --all --human-readable

4.1 如何查帮助

console
[mia@linux ~]$ ls --help | head
Usage: ls [OPTION]... [FILE]...
List information about the FILEs ...

[mia@linux ~]$ man ls
LS(1)                       User Commands                      LS(1)

man 中:

按键 作用
Space / PageDown 下一页
b / PageUp 上一页
/word 向下搜索
n / N 下一个/上一个匹配
q 退出

手册分章节,例如:

console
$ man 1 passwd    # passwd 命令
$ man 5 passwd    # /etc/passwd 文件格式

5. 查看目录:ls

console
[mia@linux ~]$ ls -lah ~/linux-lab
total 0
drwxr-xr-x 6 mia mia  59 Jul 29 09:00 .
drwx------ 8 mia mia 190 Jul 29 08:50 ..
drwxr-xr-x 2 mia mia  39 Jul 29 09:00 app
drwxr-xr-x 2 mia mia   6 Jul 29 09:00 backup
drwxr-xr-x 2 mia mia  23 Jul 29 09:00 data
drwxr-xr-x 2 mia mia  21 Jul 29 09:00 logs

常用选项:

选项 含义
-l 长格式
-a 包括隐藏项
-h 配合 -l,用 KiB、MiB、GiB 等易读单位
-t 按修改时间排序
-r 反向排序
-d 查看目录本身,不列出目录内容
-i 显示 inode 号

ls -l 一行大致包含:

text
-rw-r--r-- 1 mia developers 245 Jul 29 09:05 app.log
│          │ │   │         │   │             └─ 名称
│          │ │   │         │   └─ 修改时间
│          │ │   │         └─ 大小
│          │ │   └─ 所属组
│          │ └─ 所属用户
│          └─ 硬链接数
└─ 文件类型与权限

不要用解析 ls 输出的方式编写严肃脚本;文件名可能包含空格、换行等特殊字符。脚本中更适合使用 find -print0 等安全接口。


6. 创建目录和文件

6.1 mkdir

console
[mia@linux ~]$ mkdir ~/demo

[mia@linux ~]$ mkdir ~/a/b/c
mkdir: cannot create directory ‘/home/mia/a/b/c’: No such file or directory

[mia@linux ~]$ mkdir -p ~/a/b/c
[mia@linux ~]$ ls -d ~/a/b/c
/home/mia/a/b/c
  • -p:父目录不存在时一起创建;目录已存在时不报错。
  • 一次创建多个同级目录可用花括号展开:
console
$ mkdir -p project/{src,tests,docs,logs}

花括号展开由 Shell 完成,不是 mkdir 独有功能。

6.2 touch

console
[mia@linux ~]$ touch notes.txt
[mia@linux ~]$ ls -l notes.txt
-rw-r--r-- 1 mia mia 0 Jul 29 10:12 notes.txt

touch 的准确作用是更新访问/修改时间;文件不存在时才会顺便创建空文件。

console
[mia@linux ~]$ stat -c '%y %n' notes.txt
2026-07-29 10:12:00.000000000 -0700 notes.txt

[mia@linux ~]$ touch notes.txt
[mia@linux ~]$ stat -c '%y %n' notes.txt
2026-07-29 10:15:34.000000000 -0700 notes.txt

6.3 filestat

console
[mia@linux ~]$ file ~/linux-lab/app/main.py
/home/mia/linux-lab/app/main.py: empty

[mia@linux ~]$ stat ~/linux-lab/logs/app.log
  File: /home/mia/linux-lab/logs/app.log
  Size: 281        Blocks: 8          IO Block: 4096 regular file
Access: (0644/-rw-r--r--)  Uid: (1000/mia)   Gid: (1000/mia)

7. 查看文件内容

7.1 怎么选命令

场景 命令
小文件一次全部输出 cat file
大文件分页查看 less file
查看开头 head file
查看结尾 tail file
持续跟踪日志 tail -f filetail -F file
带行号查看 nl -ba fileless -N file

7.2 cat

console
[mia@linux ~]$ cat ~/linux-lab/app/config.env
DEBUG=false
PORT=8000

[mia@linux ~]$ cat -n ~/linux-lab/app/config.env
     1  DEBUG=false
     2  PORT=8000

cat 还能连接多个文件:

console
$ cat part1.txt part2.txt > all.txt

7.3 less

console
[mia@linux ~]$ less -N /etc/services

常用按键与 man 类似:Space 翻页、/关键词 搜索、n 下一个、q 退出。less 通常比 more 功能更完整。

7.4 headtail

console
[mia@linux ~]$ head -n 2 ~/linux-lab/logs/app.log
2026-07-29 09:00:01 INFO  server started port=8000
2026-07-29 09:02:16 INFO  GET /posts status=200

[mia@linux ~]$ tail -n 2 ~/linux-lab/logs/app.log
2026-07-29 09:04:03 WARN  slow request cost=1.82s
2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload

持续追踪:

console
[mia@linux ~]$ tail -f ~/linux-lab/logs/app.log
2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload

另一个终端追加内容:

console
[mia@linux ~]$ echo '2026-07-29 09:08:11 INFO  worker ready' >> ~/linux-lab/logs/app.log

tail -F 在日志轮转、文件被重新创建后会尝试继续跟踪,比 -f 更适合长期盯日志。


8. 复制、移动与删除

8.1 cp

console
[mia@linux ~]$ cp ~/linux-lab/app/config.env ~/linux-lab/backup/config.env.bak

[mia@linux ~]$ cp -r ~/linux-lab/app ~/linux-lab/backup/

[mia@linux ~]$ cp -a ~/linux-lab/app ~/linux-lab/backup/app-full
选项 含义
-r / -R 递归复制目录
-a 归档复制,尽量保留权限、时间、链接等属性
-i 覆盖前询问
-n 不覆盖已有目标
-v 显示操作过程

复制多个源时,最后一个参数必须是已存在的目录:

console
$ cp a.txt b.txt backup/

8.2 mv

mv 同时承担移动和重命名:

console
[mia@linux ~]$ mv old.txt new.txt

[mia@linux ~]$ mv new.txt ~/linux-lab/backup/
  • 目标不存在:通常表示重命名。
  • 目标是已存在的目录:移动到该目录内。
  • 同一文件系统内移动通常只修改目录项,很快;跨文件系统时可能变成复制后删除。

8.3 rm

console
[mia@linux ~]$ rm old.log
[mia@linux ~]$ rm -r old-directory
[mia@linux ~]$ rm -i important.conf
rm: remove regular file 'important.conf'? n
选项 含义
-r 递归删除目录
-f 强制,不询问并忽略不存在的文件
-i 每次删除前询问
-I 大量删除或递归删除前询问一次

rm 默认是否询问与别名和选项有关,不是简单按“普通用户/root”区分。

8.4 删除前的安全习惯

console
# 1. 先打印目标
[mia@linux logs]$ printf '<%s>\n' *.log
<app.log>
<old.log>

# 2. 再删除,并让危险操作询问一次
[mia@linux logs]$ rm -I -- *.log
rm: remove 2 arguments? n
  • 先用 pwdlsprintf 确认当前目录和通配结果。
  • -- 表示选项结束,可安全处理名称以 - 开头的文件。
  • 不要执行 rm -rf /rm -rf /* 或目标变量未经检查的递归删除。
  • 命令行 rm 通常不经过回收站。

删除空目录可用:

console
$ rmdir empty-directory

9. 通配符、引号与命令替换

9.1 通配符

写法 匹配
* 任意长度字符,通常不跨 /
? 任意一个字符
[abc] abc 中任一个
[0-9] 任一个数字
[!0-9] 任一个非数字字符
console
[mia@linux logs]$ printf '%s\n' *.log
app.log
old.log

[mia@linux data]$ printf '%s\n' user?.txt
user1.txt
user2.txt

通配符一般先由 Shell 展开,再把结果交给命令。

9.2 单引号、双引号与不加引号

console
[mia@linux ~]$ name='Linux'

[mia@linux ~]$ echo '$name'
$name

[mia@linux ~]$ echo "$name"
Linux

[mia@linux ~]$ echo *.txt
notes.txt report.txt

[mia@linux ~]$ echo "*.txt"
*.txt
写法 变量展开 命令替换 通配展开 保留空格
不加引号
"双引号"
'单引号'

变量引用通常写成 "$var",避免空格和通配符造成意外拆分。

9.3 命令替换

推荐使用 $(...),可读性和嵌套性优于旧式反引号:

console
[mia@linux ~]$ echo "当前目录:$(pwd)"
当前目录:/home/mia

[mia@linux ~]$ today=$(date +%F)
[mia@linux ~]$ echo "$today"
2026-07-29

10. 查找命令与文件

10.1 typecommand -vwhich

console
[mia@linux ~]$ type cd
cd is a shell builtin

[mia@linux ~]$ type -a python
python is /home/mia/venv/bin/python
python is /usr/bin/python

[mia@linux ~]$ command -v grep
/usr/bin/grep
  • type 能识别别名、函数、Shell 内建和外部命令。
  • command -v 适合脚本判断命令是否存在。
  • which 主要搜索 PATH 中的可执行文件,对别名和内建命令不一定可靠。

10.2 find 基本结构

text
find 搜索起点 条件 动作

按名称:

console
[mia@linux ~]$ find ~/linux-lab -name 'app.log'
/home/mia/linux-lab/logs/app.log

[mia@linux ~]$ find ~/linux-lab -iname '*.ENV'
/home/mia/linux-lab/app/config.env

通配模式要加引号,避免被当前 Shell 提前展开。

按类型:

console
$ find ~/linux-lab -type f     # 普通文件
$ find ~/linux-lab -type d     # 目录
$ find ~/linux-lab -type l     # 符号链接

按大小:

console
$ find /var/log -type f -size +100M
$ find . -type f -size -10k

按修改时间:

console
$ find . -type f -mtime -1     # 约 24 小时内修改
$ find . -type f -mtime +30    # 超过约 30 天
$ find . -type f -mmin -10     # 约 10 分钟内修改

组合条件:

console
$ find . -type f \( -name '*.log' -o -name '*.txt' \)
$ find . -type f -name '*.log' ! -name 'debug.log'

对结果执行命令:

console
[mia@linux ~]$ find ~/linux-lab/logs -type f -name '*.log' \
> -exec grep -Hn 'ERROR' {} +
/home/mia/linux-lab/logs/app.log:3:2026-07-29 09:03:40 ERROR database timeout request_id=r101
/home/mia/linux-lab/logs/app.log:5:2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload

{} + 会把多个结果成批传给命令,通常比每个文件执行一次的 {} \; 更高效。


11. 文本过滤与统计

11.1 grep

console
[mia@linux ~]$ grep -n 'ERROR' ~/linux-lab/logs/app.log
3:2026-07-29 09:03:40 ERROR database timeout request_id=r101
5:2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload

常用选项:

选项 含义
-n 显示行号
-i 忽略大小写
-v 反选,不含匹配内容
-r 递归搜索目录
-l 只显示匹配到的文件名
-c 显示每个文件的匹配行数
-E 使用扩展正则表达式
-F 把模式当普通字符串,不解释正则符号
-A 2 显示匹配行及后 2 行
-B 2 显示匹配行及前 2 行
-C 2 显示匹配行前后各 2 行
console
[mia@linux ~]$ grep -E 'ERROR|WARN' ~/linux-lab/logs/app.log
2026-07-29 09:03:40 ERROR database timeout request_id=r101
2026-07-29 09:04:03 WARN  slow request cost=1.82s
2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload

[mia@linux ~]$ grep -rln 'DEBUG=false' ~/linux-lab
/home/mia/linux-lab/app/config.env

11.2 wc

console
[mia@linux ~]$ wc ~/linux-lab/data/users.txt
  4  16 105 /home/mia/linux-lab/data/users.txt

默认依次显示行数、单词数、字节数。

console
$ wc -l file       # 行数
$ wc -w file       # 单词数
$ wc -c file       # 字节数
$ wc -m file       # 字符数

UTF-8 中文字符通常占多个字节,因此 -c-m 可能不同。

11.3 sortuniqcut

统计每种状态的人数:

console
[mia@linux ~]$ awk '{print $4}' ~/linux-lab/data/users.txt | sort | uniq -c
      3 active
      1 disabled

uniq 只合并相邻重复行,所以一般先 sort

/etc/passwd 提取用户名和登录 Shell:

console
[mia@linux ~]$ cut -d: -f1,7 /etc/passwd | head
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
...

12. 管道与重定向

12.1 三个标准流

编号 名称 默认位置
0 标准输入 stdin 键盘
1 标准输出 stdout 终端
2 标准错误 stderr 终端

12.2 管道 |

管道把左侧命令的标准输出交给右侧命令的标准输入

console
[mia@linux ~]$ grep 'ERROR' ~/linux-lab/logs/app.log | wc -l
2

[mia@linux ~]$ ps -ef | grep '[g]unicorn'
mia       3184       1  0 09:00 ?  00:00:01 gunicorn: master [config.wsgi]

grep '[g]unicorn' 可以避免把当前 grep gunicorn 自己匹配出来。更直接的做法是:

console
$ pgrep -af gunicorn

管道默认不传递标准错误:

console
$ find / -name '*.conf' 2>/dev/null | head

12.3 输出重定向

console
$ echo 'DEBUG=false' > config.env       # 覆盖标准输出
$ echo 'PORT=8000' >> config.env        # 追加标准输出
$ command 2> error.log                  # 只重定向错误
$ command > output.log 2> error.log     # 输出和错误分开
$ command > all.log 2>&1                # 二者写入同一文件
$ command &> all.log                    # Bash 简写
$ command > /dev/null 2>&1              # 丢弃输出与错误

顺序很重要:

console
$ command > all.log 2>&1    # stderr 跟随已经指向 all.log 的 stdout
$ command 2>&1 > all.log    # stderr 先指向终端,之后只有 stdout 改到文件

12.4 输入重定向与 Here Document

console
$ wc -l < users.txt
4

批量写入多行文本:

console
[mia@linux ~]$ cat > settings.ini <<'EOF'
[app]
debug = false
port = 8000
EOF

分隔符加单引号后,正文中的 $变量$(命令) 不会展开。

12.5 tee

既在屏幕显示又保存:

console
[mia@linux ~]$ grep -E 'ERROR|WARN' ~/linux-lab/logs/app.log | tee ~/linux-lab/backup/problems.log
2026-07-29 09:03:40 ERROR database timeout request_id=r101
2026-07-29 09:04:03 WARN  slow request cost=1.82s
2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload

追加使用 tee -a。写入需要 root 权限的文件时:

console
$ echo '127.0.0.1 forum.local' | sudo tee -a /etc/hosts

sudo echo ... > /etc/hosts 往往失败,因为重定向由当前普通 Shell 提前完成,sudo 只作用于 echo


13. 命令连接与退出状态

写法 含义
cmd1 ; cmd2 无论前者成功与否都执行后者
cmd1 && cmd2 前者成功才执行后者
`cmd1
cmd1 | cmd2 前者输出作为后者输入
console
[mia@linux ~]$ mkdir release && cp app.py release/

[mia@linux ~]$ test -f config.env || echo 'config.env 不存在'
config.env 不存在

Linux 命令通常用退出状态表示结果:

  • 0:成功;
  • 0:失败或出现特定情况。
console
[mia@linux ~]$ grep 'ERROR' ~/linux-lab/logs/app.log >/dev/null
[mia@linux ~]$ echo $?
0

[mia@linux ~]$ grep 'FATAL' ~/linux-lab/logs/app.log >/dev/null
[mia@linux ~]$ echo $?
1

$? 只保存最近一条前台命令的状态,应立即查看。


14. 安全地批量处理文件:xargs

简单形式:

console
$ printf '%s\n' a.log b.log | xargs rm

但文件名可能包含空格或换行,严肃场景使用 NUL 分隔:

console
$ find logs -type f -name '*.log' -print0 | xargs -0 grep -Hn 'ERROR'

许多场景可直接用 find -exec ... {} +,这样不需要额外考虑结果如何传递。


15. Vim 面试够用版

15.1 三种主要模式

模式 进入方式 作用
普通模式 打开文件或按 Esc 移动、复制、删除、搜索
插入模式 iao 输入文字
命令行模式 普通模式按 :/? 保存、退出、搜索、替换
console
[mia@linux ~]$ vim ~/linux-lab/app/config.env

最短操作流程:

text
i        进入插入模式
输入内容
Esc      回到普通模式
:wq      保存并退出

15.2 高频按键

按键 作用
h j k l 左、下、上、右
0 / $ 行首/行尾
gg / G 文件首/文件尾
w / b 下一个/上一个单词
i / a 光标前/后插入
o / O 下方/上方新建一行
dd 删除/剪切当前行
yy 复制当前行
p 粘贴到光标后
u 撤销
Ctrl+r 重做
/word 向下搜索
n / N 下一个/上一个匹配

15.3 保存、退出与替换

命令 作用
:w 保存
:q 退出
:wqZZ 保存并退出
:q! 放弃修改并退出
:set number 显示行号
:%s/old/new/g 全文件替换
:%s/old/new/gc 全文件替换,每次确认

16. 高频实战题

16.1 统计日志中 ERROR 数量

console
[mia@linux ~]$ grep -c 'ERROR' ~/linux-lab/logs/app.log
2

若需要统计匹配结果行数,也可:

console
$ grep 'ERROR' app.log | wc -l

16.2 找出 /var/log 下大于 100 MiB 的日志

console
$ sudo find /var/log -type f -name '*.log' -size +100M -print

16.3 查找项目中写死的密码字段

console
$ grep -RniE 'password|secret|token' ./project \
  --exclude-dir=.git --exclude='*.pyc'

16.4 保留最近结果,同时记录错误

console
$ python manage.py migrate > migrate.log 2>&1
$ tail -n 30 migrate.log

16.5 把最近一天的 .log 文件归档到目录

先只查看:

console
$ find ./logs -type f -name '*.log' -mtime -1 -print

确认后再复制:

console
$ mkdir -p backup/recent
$ find ./logs -type f -name '*.log' -mtime -1 -exec cp -t backup/recent -- {} +

17. 高频面试问答

17.1 绝对路径和相对路径有什么区别?

绝对路径从根目录 / 开始,不依赖当前目录;相对路径从当前工作目录开始,结果会受 pwd 影响。

17.2 >>> 有什么区别?

> 覆盖目标文件,>> 追加到文件尾部。两者默认只处理标准输出,错误输出需要使用 2> 等写法。

17.3 管道和重定向有什么区别?

管道把一个命令的标准输出交给另一个命令的标准输入;重定向改变标准输入、标准输出或标准错误所连接的位置,通常是文件。

17.4 findgrep 的区别?

find 主要按名称、类型、大小、时间等文件属性查找文件;grep 主要在文本内容中查找匹配行。两者经常组合使用。

17.5 which 为什么找不到 cd

cd 通常是 Shell 内建命令,不是通过 PATH 搜索的普通外部程序。使用 type cd 能正确识别它。

17.6 tail -ftail -F 的区别?

-f 持续读取当前文件描述符;-F 还会按文件名重试,日志轮转导致原文件被替换时更容易继续追踪。

17.7 为什么 rm -rf 危险?

-r 会递归遍历目录,-f 取消确认和多数报错。如果路径、变量或通配符写错,可能快速删除大量数据,而且通常无法从回收站恢复。

17.8 单引号和双引号有什么区别?

单引号基本保留全部字面内容,不展开变量和命令;双引号会展开 $变量$(命令),但保留空格并阻止通配展开。

17.9 2>&1 是什么意思?

让文件描述符 2(标准错误)指向文件描述符 1(标准输出)当前指向的位置。它与前后重定向的顺序有关。

17.10 如何统计出现次数最多的 IP?

假设访问日志第一列是 IP:

console
$ awk '{print $1}' access.log | sort | uniq -c | sort -nr | head

18. 最终自测

不看答案完成以下任务:

  1. 在家目录创建 review/{src,logs,backup}
  2. 创建三行日志,其中两行包含 ERROR
  3. 显示日志最后两行并持续跟踪。
  4. 统计 ERROR 行数。
  5. 把标准输出和错误同时保存到 run.log
  6. 查找当前目录下 24 小时内修改的 .py 文件。
  7. 递归搜索项目中出现 DEBUG=True 的文件并显示行号。
  8. 用一条命令把查询结果同时显示并保存。
  9. 解释 rm -rf "$target" 中为什么变量必须加双引号,以及为什么执行前仍要验证目标。
  10. 在 Vim 中完成搜索、替换、保存退出。

一组参考命令:

console
$ mkdir -p ~/review/{src,logs,backup}
$ printf 'INFO start\nERROR db\nERROR permission\n' > ~/review/logs/app.log
$ tail -n 2 -f ~/review/logs/app.log
$ grep -c 'ERROR' ~/review/logs/app.log
$ command > ~/review/run.log 2>&1
$ find . -type f -name '*.py' -mtime -1
$ grep -RniF 'DEBUG=True' .
$ grep -n 'ERROR' ~/review/logs/app.log | tee ~/review/backup/errors.txt

相关文章

;`#` 表示 root,复制命令时不要把提示符一起复制。\n\n## 1. 高频命令总表\n\n| 任务 | 首选命令 | 高频选项/写法 |\n|---|---|---|\n| 查看目录 | `ls` | `-l`、`-a`、`-h`、`-t` |\n| 切换/确认目录 | `cd`、`pwd` | `cd ..`、`cd -`、`cd ~` |\n| 创建目录/文件 | `mkdir`、`touch` | `mkdir -p` |\n| 查看文件 | `cat`、`less`、`head`、`tail` | `less -N`、`tail -f`、`tail -F` |\n| 查看文件信息 | `file`、`stat` | `stat 文件` |\n| 复制/移动 | `cp`、`mv` | `cp -a`、`cp -r`、`-i` |\n| 删除 | `rm`、`rmdir` | `rm -r`、`rm -i` |\n| 查找文件 | `find` | `-name`、`-type`、`-size`、`-mtime` |\n| 查找命令 | `type`、`command -v` | `type -a` |\n| 过滤内容 | `grep` | `-n`、`-i`、`-r`、`-E`、`-v` |\n| 统计内容 | `wc` | `-l`、`-w`、`-c`、`-m` |\n| 排序去重 | `sort`、`uniq` | `sort -n`、`sort -u`、`uniq -c` |\n| 提取列 | `cut`、`awk` | `cut -d: -f1` |\n| 管道 | `|` | 左边标准输出交给右边标准输入 |\n| 重定向 | `\u003e`、`\u003e\u003e`、`2\u003e` | 覆盖、追加、重定向错误 |\n| 同时看并保存 | `tee` | `命令 | tee 文件` |\n| 编辑文件 | `vim` | `i`、`Esc`、`:wq`、`:q!` |\n| 查帮助 | `--help`、`man` | `man 5 passwd` |\n\n### 必须认识的目录\n\n| 目录 | 主要内容 |\n|---|---|\n| `/` | 整棵目录树的根 |\n| `/home` | 普通用户家目录 |\n| `/root` | root 的家目录,不是根目录 `/` |\n| `/etc` | 系统和服务配置 |\n| `/var` | 经常变化的数据,如日志、缓存、队列 |\n| `/var/log` | 常见日志目录 |\n| `/usr/bin` | 大量普通命令 |\n| `/usr/sbin` | 大量系统管理命令 |\n| `/tmp` | 临时文件,可能被系统清理 |\n| `/opt` | 可选的第三方软件 |\n| `/srv` | 服务对外提供的数据 |\n| `/dev` | 设备文件 |\n| `/proc` | 内核和进程信息的虚拟文件系统 |\n| `/sys` | 设备与内核对象信息的虚拟文件系统 |\n\n---\n\n## 2. 先准备一套统一练习数据\n\n后面的命令都围绕 `~/linux-lab` 演示:\n\n```console\n[mia@linux ~]$ mkdir -p ~/linux-lab/{app,data,logs,backup}\n\n[mia@linux ~]$ cat \u003e ~/linux-lab/data/users.txt \u003c\u003c'EOF'\n1001 alice backend active\n1002 bob frontend active\n1003 carol backend disabled\n1004 dave ops active\nEOF\n\n[mia@linux ~]$ cat \u003e ~/linux-lab/logs/app.log \u003c\u003c'EOF'\n2026-07-29 09:00:01 INFO server started port=8000\n2026-07-29 09:02:16 INFO GET /posts status=200\n2026-07-29 09:03:40 ERROR database timeout request_id=r101\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\nEOF\n\n[mia@linux ~]$ printf 'DEBUG=false\\nPORT=8000\\n' \u003e ~/linux-lab/app/config.env\n[mia@linux ~]$ touch ~/linux-lab/app/main.py\n```\n\n查看结构:\n\n```console\n[mia@linux ~]$ find ~/linux-lab -maxdepth 2 -printf '%P\\n' | sort\n\napp\napp/config.env\napp/main.py\nbackup\ndata\ndata/users.txt\nlogs\nlogs/app.log\n```\n\n开头出现的空行代表 `~/linux-lab` 本身;这是 `find` 的正常结果。\n\n---\n\n## 3. Linux 目录树与路径\n\n### 3.1 Linux 只有一棵目录树\n\nWindows 常见 `C:\\`、`D:\\` 多个盘符;Linux 从唯一的根目录 `/` 开始。其他磁盘和文件系统通常被**挂载**到这棵树的某个目录。\n\n```text\n/\n├── etc\n├── home\n│ └── mia\n├── usr\n├── var\n└── ...\n```\n\n### 3.2 绝对路径与相对路径\n\n| 路径 | 起点 | 示例 |\n|---|---|---|\n| 绝对路径 | 根目录 `/` | `/home/mia/linux-lab/logs/app.log` |\n| 相对路径 | 当前工作目录 | `logs/app.log` |\n\n```console\n[mia@linux ~]$ cd ~/linux-lab\n[mia@linux linux-lab]$ pwd\n/home/mia/linux-lab\n\n[mia@linux linux-lab]$ cat logs/app.log\n2026-07-29 09:00:01 INFO server started port=8000\n...\n\n[mia@linux linux-lab]$ cat /home/mia/linux-lab/logs/app.log\n2026-07-29 09:00:01 INFO server started port=8000\n...\n```\n\n### 3.3 特殊路径\n\n| 写法 | 含义 |\n|---|---|\n| `.` | 当前目录 |\n| `..` | 上一级目录 |\n| `~` | 当前用户家目录 |\n| `~alice` | 用户 alice 的家目录 |\n| `-` | `cd` 中表示上一次所在目录 |\n\n```console\n[mia@linux linux-lab]$ cd logs\n[mia@linux logs]$ cd ..\n[mia@linux linux-lab]$ cd -\n/home/mia/linux-lab/logs\n[mia@linux logs]$ cd\n[mia@linux ~]$\n```\n\n`cd` 不带参数等价于回到当前用户的家目录。\n\n### 3.4 文件名、隐藏文件与大小写\n\n- 以 `.` 开头的名称默认隐藏,例如 `.bashrc`。\n- Linux 文件名通常区分大小写:`App.py` 与 `app.py` 是两个名称。\n- 扩展名不决定文件本质,`file` 会根据内容判断类型。\n\n```console\n[mia@linux ~]$ ls\nlinux-lab\n\n[mia@linux ~]$ ls -a\n. .. .bashrc .ssh linux-lab\n\n[mia@linux ~]$ file ~/linux-lab/logs/app.log\n/home/mia/linux-lab/logs/app.log: ASCII text\n```\n\n---\n\n## 4. 命令的基本结构\n\n常见形式:\n\n```text\ncommand [options] [arguments]\n```\n\n```console\n[mia@linux ~]$ ls -lah ~/linux-lab\n```\n\n- `ls`:命令;\n- `-l`、`-a`、`-h`:选项;\n- `~/linux-lab`:参数。\n\n短选项常可合并,下面三种通常等价:\n\n```console\n$ ls -l -a -h\n$ ls -lah\n$ ls -hal\n```\n\n长选项通常以两个连字符开头:\n\n```console\n$ ls --all --human-readable\n```\n\n### 4.1 如何查帮助\n\n```console\n[mia@linux ~]$ ls --help | head\nUsage: ls [OPTION]... [FILE]...\nList information about the FILEs ...\n\n[mia@linux ~]$ man ls\nLS(1) User Commands LS(1)\n```\n\n在 `man` 中:\n\n| 按键 | 作用 |\n|---|---|\n| `Space` / `PageDown` | 下一页 |\n| `b` / `PageUp` | 上一页 |\n| `/word` | 向下搜索 |\n| `n` / `N` | 下一个/上一个匹配 |\n| `q` | 退出 |\n\n手册分章节,例如:\n\n```console\n$ man 1 passwd # passwd 命令\n$ man 5 passwd # /etc/passwd 文件格式\n```\n\n---\n\n## 5. 查看目录:`ls`\n\n```console\n[mia@linux ~]$ ls -lah ~/linux-lab\ntotal 0\ndrwxr-xr-x 6 mia mia 59 Jul 29 09:00 .\ndrwx------ 8 mia mia 190 Jul 29 08:50 ..\ndrwxr-xr-x 2 mia mia 39 Jul 29 09:00 app\ndrwxr-xr-x 2 mia mia 6 Jul 29 09:00 backup\ndrwxr-xr-x 2 mia mia 23 Jul 29 09:00 data\ndrwxr-xr-x 2 mia mia 21 Jul 29 09:00 logs\n```\n\n常用选项:\n\n| 选项 | 含义 |\n|---|---|\n| `-l` | 长格式 |\n| `-a` | 包括隐藏项 |\n| `-h` | 配合 `-l`,用 KiB、MiB、GiB 等易读单位 |\n| `-t` | 按修改时间排序 |\n| `-r` | 反向排序 |\n| `-d` | 查看目录本身,不列出目录内容 |\n| `-i` | 显示 inode 号 |\n\n`ls -l` 一行大致包含:\n\n```text\n-rw-r--r-- 1 mia developers 245 Jul 29 09:05 app.log\n│ │ │ │ │ │ └─ 名称\n│ │ │ │ │ └─ 修改时间\n│ │ │ │ └─ 大小\n│ │ │ └─ 所属组\n│ │ └─ 所属用户\n│ └─ 硬链接数\n└─ 文件类型与权限\n```\n\n不要用解析 `ls` 输出的方式编写严肃脚本;文件名可能包含空格、换行等特殊字符。脚本中更适合使用 `find -print0` 等安全接口。\n\n---\n\n## 6. 创建目录和文件\n\n### 6.1 `mkdir`\n\n```console\n[mia@linux ~]$ mkdir ~/demo\n\n[mia@linux ~]$ mkdir ~/a/b/c\nmkdir: cannot create directory ‘/home/mia/a/b/c’: No such file or directory\n\n[mia@linux ~]$ mkdir -p ~/a/b/c\n[mia@linux ~]$ ls -d ~/a/b/c\n/home/mia/a/b/c\n```\n\n- `-p`:父目录不存在时一起创建;目录已存在时不报错。\n- 一次创建多个同级目录可用花括号展开:\n\n```console\n$ mkdir -p project/{src,tests,docs,logs}\n```\n\n花括号展开由 Shell 完成,不是 `mkdir` 独有功能。\n\n### 6.2 `touch`\n\n```console\n[mia@linux ~]$ touch notes.txt\n[mia@linux ~]$ ls -l notes.txt\n-rw-r--r-- 1 mia mia 0 Jul 29 10:12 notes.txt\n```\n\n`touch` 的准确作用是更新访问/修改时间;文件不存在时才会顺便创建空文件。\n\n```console\n[mia@linux ~]$ stat -c '%y %n' notes.txt\n2026-07-29 10:12:00.000000000 -0700 notes.txt\n\n[mia@linux ~]$ touch notes.txt\n[mia@linux ~]$ stat -c '%y %n' notes.txt\n2026-07-29 10:15:34.000000000 -0700 notes.txt\n```\n\n### 6.3 `file` 与 `stat`\n\n```console\n[mia@linux ~]$ file ~/linux-lab/app/main.py\n/home/mia/linux-lab/app/main.py: empty\n\n[mia@linux ~]$ stat ~/linux-lab/logs/app.log\n File: /home/mia/linux-lab/logs/app.log\n Size: 281 Blocks: 8 IO Block: 4096 regular file\nAccess: (0644/-rw-r--r--) Uid: (1000/mia) Gid: (1000/mia)\n```\n\n---\n\n## 7. 查看文件内容\n\n### 7.1 怎么选命令\n\n| 场景 | 命令 |\n|---|---|\n| 小文件一次全部输出 | `cat file` |\n| 大文件分页查看 | `less file` |\n| 查看开头 | `head file` |\n| 查看结尾 | `tail file` |\n| 持续跟踪日志 | `tail -f file` 或 `tail -F file` |\n| 带行号查看 | `nl -ba file` 或 `less -N file` |\n\n### 7.2 `cat`\n\n```console\n[mia@linux ~]$ cat ~/linux-lab/app/config.env\nDEBUG=false\nPORT=8000\n\n[mia@linux ~]$ cat -n ~/linux-lab/app/config.env\n 1 DEBUG=false\n 2 PORT=8000\n```\n\n`cat` 还能连接多个文件:\n\n```console\n$ cat part1.txt part2.txt \u003e all.txt\n```\n\n### 7.3 `less`\n\n```console\n[mia@linux ~]$ less -N /etc/services\n```\n\n常用按键与 `man` 类似:`Space` 翻页、`/关键词` 搜索、`n` 下一个、`q` 退出。`less` 通常比 `more` 功能更完整。\n\n### 7.4 `head` 与 `tail`\n\n```console\n[mia@linux ~]$ head -n 2 ~/linux-lab/logs/app.log\n2026-07-29 09:00:01 INFO server started port=8000\n2026-07-29 09:02:16 INFO GET /posts status=200\n\n[mia@linux ~]$ tail -n 2 ~/linux-lab/logs/app.log\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\n```\n\n持续追踪:\n\n```console\n[mia@linux ~]$ tail -f ~/linux-lab/logs/app.log\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\n```\n\n另一个终端追加内容:\n\n```console\n[mia@linux ~]$ echo '2026-07-29 09:08:11 INFO worker ready' \u003e\u003e ~/linux-lab/logs/app.log\n```\n\n`tail -F` 在日志轮转、文件被重新创建后会尝试继续跟踪,比 `-f` 更适合长期盯日志。\n\n---\n\n## 8. 复制、移动与删除\n\n### 8.1 `cp`\n\n```console\n[mia@linux ~]$ cp ~/linux-lab/app/config.env ~/linux-lab/backup/config.env.bak\n\n[mia@linux ~]$ cp -r ~/linux-lab/app ~/linux-lab/backup/\n\n[mia@linux ~]$ cp -a ~/linux-lab/app ~/linux-lab/backup/app-full\n```\n\n| 选项 | 含义 |\n|---|---|\n| `-r` / `-R` | 递归复制目录 |\n| `-a` | 归档复制,尽量保留权限、时间、链接等属性 |\n| `-i` | 覆盖前询问 |\n| `-n` | 不覆盖已有目标 |\n| `-v` | 显示操作过程 |\n\n复制多个源时,最后一个参数必须是已存在的目录:\n\n```console\n$ cp a.txt b.txt backup/\n```\n\n### 8.2 `mv`\n\n`mv` 同时承担移动和重命名:\n\n```console\n[mia@linux ~]$ mv old.txt new.txt\n\n[mia@linux ~]$ mv new.txt ~/linux-lab/backup/\n```\n\n- 目标不存在:通常表示重命名。\n- 目标是已存在的目录:移动到该目录内。\n- 同一文件系统内移动通常只修改目录项,很快;跨文件系统时可能变成复制后删除。\n\n### 8.3 `rm`\n\n```console\n[mia@linux ~]$ rm old.log\n[mia@linux ~]$ rm -r old-directory\n[mia@linux ~]$ rm -i important.conf\nrm: remove regular file 'important.conf'? n\n```\n\n| 选项 | 含义 |\n|---|---|\n| `-r` | 递归删除目录 |\n| `-f` | 强制,不询问并忽略不存在的文件 |\n| `-i` | 每次删除前询问 |\n| `-I` | 大量删除或递归删除前询问一次 |\n\n`rm` 默认是否询问与别名和选项有关,不是简单按“普通用户/root”区分。\n\n### 8.4 删除前的安全习惯\n\n```console\n# 1. 先打印目标\n[mia@linux logs]$ printf '\u003c%s\u003e\\n' *.log\n\u003capp.log\u003e\n\u003cold.log\u003e\n\n# 2. 再删除,并让危险操作询问一次\n[mia@linux logs]$ rm -I -- *.log\nrm: remove 2 arguments? n\n```\n\n- 先用 `pwd`、`ls` 或 `printf` 确认当前目录和通配结果。\n- `--` 表示选项结束,可安全处理名称以 `-` 开头的文件。\n- 不要执行 `rm -rf /`、`rm -rf /*` 或目标变量未经检查的递归删除。\n- 命令行 `rm` 通常不经过回收站。\n\n删除空目录可用:\n\n```console\n$ rmdir empty-directory\n```\n\n---\n\n## 9. 通配符、引号与命令替换\n\n### 9.1 通配符\n\n| 写法 | 匹配 |\n|---|---|\n| `*` | 任意长度字符,通常不跨 `/` |\n| `?` | 任意一个字符 |\n| `[abc]` | `a`、`b`、`c` 中任一个 |\n| `[0-9]` | 任一个数字 |\n| `[!0-9]` | 任一个非数字字符 |\n\n```console\n[mia@linux logs]$ printf '%s\\n' *.log\napp.log\nold.log\n\n[mia@linux data]$ printf '%s\\n' user?.txt\nuser1.txt\nuser2.txt\n```\n\n通配符一般先由 Shell 展开,再把结果交给命令。\n\n### 9.2 单引号、双引号与不加引号\n\n```console\n[mia@linux ~]$ name='Linux'\n\n[mia@linux ~]$ echo '$name'\n$name\n\n[mia@linux ~]$ echo \"$name\"\nLinux\n\n[mia@linux ~]$ echo *.txt\nnotes.txt report.txt\n\n[mia@linux ~]$ echo \"*.txt\"\n*.txt\n```\n\n| 写法 | 变量展开 | 命令替换 | 通配展开 | 保留空格 |\n|---|---:|---:|---:|---:|\n| 不加引号 | 是 | 是 | 是 | 否 |\n| `\"双引号\"` | 是 | 是 | 否 | 是 |\n| `'单引号'` | 否 | 否 | 否 | 是 |\n\n变量引用通常写成 `\"$var\"`,避免空格和通配符造成意外拆分。\n\n### 9.3 命令替换\n\n推荐使用 `$(...)`,可读性和嵌套性优于旧式反引号:\n\n```console\n[mia@linux ~]$ echo \"当前目录:$(pwd)\"\n当前目录:/home/mia\n\n[mia@linux ~]$ today=$(date +%F)\n[mia@linux ~]$ echo \"$today\"\n2026-07-29\n```\n\n---\n\n## 10. 查找命令与文件\n\n### 10.1 `type`、`command -v`、`which`\n\n```console\n[mia@linux ~]$ type cd\ncd is a shell builtin\n\n[mia@linux ~]$ type -a python\npython is /home/mia/venv/bin/python\npython is /usr/bin/python\n\n[mia@linux ~]$ command -v grep\n/usr/bin/grep\n```\n\n- `type` 能识别别名、函数、Shell 内建和外部命令。\n- `command -v` 适合脚本判断命令是否存在。\n- `which` 主要搜索 `PATH` 中的可执行文件,对别名和内建命令不一定可靠。\n\n### 10.2 `find` 基本结构\n\n```text\nfind 搜索起点 条件 动作\n```\n\n按名称:\n\n```console\n[mia@linux ~]$ find ~/linux-lab -name 'app.log'\n/home/mia/linux-lab/logs/app.log\n\n[mia@linux ~]$ find ~/linux-lab -iname '*.ENV'\n/home/mia/linux-lab/app/config.env\n```\n\n通配模式要加引号,避免被当前 Shell 提前展开。\n\n按类型:\n\n```console\n$ find ~/linux-lab -type f # 普通文件\n$ find ~/linux-lab -type d # 目录\n$ find ~/linux-lab -type l # 符号链接\n```\n\n按大小:\n\n```console\n$ find /var/log -type f -size +100M\n$ find . -type f -size -10k\n```\n\n按修改时间:\n\n```console\n$ find . -type f -mtime -1 # 约 24 小时内修改\n$ find . -type f -mtime +30 # 超过约 30 天\n$ find . -type f -mmin -10 # 约 10 分钟内修改\n```\n\n组合条件:\n\n```console\n$ find . -type f \\( -name '*.log' -o -name '*.txt' \\)\n$ find . -type f -name '*.log' ! -name 'debug.log'\n```\n\n对结果执行命令:\n\n```console\n[mia@linux ~]$ find ~/linux-lab/logs -type f -name '*.log' \\\n\u003e -exec grep -Hn 'ERROR' {} +\n/home/mia/linux-lab/logs/app.log:3:2026-07-29 09:03:40 ERROR database timeout request_id=r101\n/home/mia/linux-lab/logs/app.log:5:2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\n```\n\n`{} +` 会把多个结果成批传给命令,通常比每个文件执行一次的 `{} \\;` 更高效。\n\n---\n\n## 11. 文本过滤与统计\n\n### 11.1 `grep`\n\n```console\n[mia@linux ~]$ grep -n 'ERROR' ~/linux-lab/logs/app.log\n3:2026-07-29 09:03:40 ERROR database timeout request_id=r101\n5:2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\n```\n\n常用选项:\n\n| 选项 | 含义 |\n|---|---|\n| `-n` | 显示行号 |\n| `-i` | 忽略大小写 |\n| `-v` | 反选,不含匹配内容 |\n| `-r` | 递归搜索目录 |\n| `-l` | 只显示匹配到的文件名 |\n| `-c` | 显示每个文件的匹配行数 |\n| `-E` | 使用扩展正则表达式 |\n| `-F` | 把模式当普通字符串,不解释正则符号 |\n| `-A 2` | 显示匹配行及后 2 行 |\n| `-B 2` | 显示匹配行及前 2 行 |\n| `-C 2` | 显示匹配行前后各 2 行 |\n\n```console\n[mia@linux ~]$ grep -E 'ERROR|WARN' ~/linux-lab/logs/app.log\n2026-07-29 09:03:40 ERROR database timeout request_id=r101\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\n\n[mia@linux ~]$ grep -rln 'DEBUG=false' ~/linux-lab\n/home/mia/linux-lab/app/config.env\n```\n\n### 11.2 `wc`\n\n```console\n[mia@linux ~]$ wc ~/linux-lab/data/users.txt\n 4 16 105 /home/mia/linux-lab/data/users.txt\n```\n\n默认依次显示行数、单词数、字节数。\n\n```console\n$ wc -l file # 行数\n$ wc -w file # 单词数\n$ wc -c file # 字节数\n$ wc -m file # 字符数\n```\n\nUTF-8 中文字符通常占多个字节,因此 `-c` 与 `-m` 可能不同。\n\n### 11.3 `sort`、`uniq`、`cut`\n\n统计每种状态的人数:\n\n```console\n[mia@linux ~]$ awk '{print $4}' ~/linux-lab/data/users.txt | sort | uniq -c\n 3 active\n 1 disabled\n```\n\n`uniq` 只合并**相邻**重复行,所以一般先 `sort`。\n\n从 `/etc/passwd` 提取用户名和登录 Shell:\n\n```console\n[mia@linux ~]$ cut -d: -f1,7 /etc/passwd | head\nroot:/bin/bash\nbin:/sbin/nologin\ndaemon:/sbin/nologin\n...\n```\n\n---\n\n## 12. 管道与重定向\n\n### 12.1 三个标准流\n\n| 编号 | 名称 | 默认位置 |\n|---:|---|---|\n| `0` | 标准输入 stdin | 键盘 |\n| `1` | 标准输出 stdout | 终端 |\n| `2` | 标准错误 stderr | 终端 |\n\n### 12.2 管道 `|`\n\n管道把左侧命令的**标准输出**交给右侧命令的**标准输入**:\n\n```console\n[mia@linux ~]$ grep 'ERROR' ~/linux-lab/logs/app.log | wc -l\n2\n\n[mia@linux ~]$ ps -ef | grep '[g]unicorn'\nmia 3184 1 0 09:00 ? 00:00:01 gunicorn: master [config.wsgi]\n```\n\n`grep '[g]unicorn'` 可以避免把当前 `grep gunicorn` 自己匹配出来。更直接的做法是:\n\n```console\n$ pgrep -af gunicorn\n```\n\n管道默认不传递标准错误:\n\n```console\n$ find / -name '*.conf' 2\u003e/dev/null | head\n```\n\n### 12.3 输出重定向\n\n```console\n$ echo 'DEBUG=false' \u003e config.env # 覆盖标准输出\n$ echo 'PORT=8000' \u003e\u003e config.env # 追加标准输出\n$ command 2\u003e error.log # 只重定向错误\n$ command \u003e output.log 2\u003e error.log # 输出和错误分开\n$ command \u003e all.log 2\u003e\u00261 # 二者写入同一文件\n$ command \u0026\u003e all.log # Bash 简写\n$ command \u003e /dev/null 2\u003e\u00261 # 丢弃输出与错误\n```\n\n顺序很重要:\n\n```console\n$ command \u003e all.log 2\u003e\u00261 # stderr 跟随已经指向 all.log 的 stdout\n$ command 2\u003e\u00261 \u003e all.log # stderr 先指向终端,之后只有 stdout 改到文件\n```\n\n### 12.4 输入重定向与 Here Document\n\n```console\n$ wc -l \u003c users.txt\n4\n```\n\n批量写入多行文本:\n\n```console\n[mia@linux ~]$ cat \u003e settings.ini \u003c\u003c'EOF'\n[app]\ndebug = false\nport = 8000\nEOF\n```\n\n分隔符加单引号后,正文中的 `$变量` 和 `$(命令)` 不会展开。\n\n### 12.5 `tee`\n\n既在屏幕显示又保存:\n\n```console\n[mia@linux ~]$ grep -E 'ERROR|WARN' ~/linux-lab/logs/app.log | tee ~/linux-lab/backup/problems.log\n2026-07-29 09:03:40 ERROR database timeout request_id=r101\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\n```\n\n追加使用 `tee -a`。写入需要 root 权限的文件时:\n\n```console\n$ echo '127.0.0.1 forum.local' | sudo tee -a /etc/hosts\n```\n\n`sudo echo ... \u003e /etc/hosts` 往往失败,因为重定向由当前普通 Shell 提前完成,`sudo` 只作用于 `echo`。\n\n---\n\n## 13. 命令连接与退出状态\n\n| 写法 | 含义 |\n|---|---|\n| `cmd1 ; cmd2` | 无论前者成功与否都执行后者 |\n| `cmd1 \u0026\u0026 cmd2` | 前者成功才执行后者 |\n| `cmd1 || cmd2` | 前者失败才执行后者 |\n| `cmd1 \\| cmd2` | 前者输出作为后者输入 |\n\n```console\n[mia@linux ~]$ mkdir release \u0026\u0026 cp app.py release/\n\n[mia@linux ~]$ test -f config.env || echo 'config.env 不存在'\nconfig.env 不存在\n```\n\nLinux 命令通常用退出状态表示结果:\n\n- `0`:成功;\n- 非 `0`:失败或出现特定情况。\n\n```console\n[mia@linux ~]$ grep 'ERROR' ~/linux-lab/logs/app.log \u003e/dev/null\n[mia@linux ~]$ echo $?\n0\n\n[mia@linux ~]$ grep 'FATAL' ~/linux-lab/logs/app.log \u003e/dev/null\n[mia@linux ~]$ echo $?\n1\n```\n\n`$?` 只保存最近一条前台命令的状态,应立即查看。\n\n---\n\n## 14. 安全地批量处理文件:`xargs`\n\n简单形式:\n\n```console\n$ printf '%s\\n' a.log b.log | xargs rm\n```\n\n但文件名可能包含空格或换行,严肃场景使用 NUL 分隔:\n\n```console\n$ find logs -type f -name '*.log' -print0 | xargs -0 grep -Hn 'ERROR'\n```\n\n许多场景可直接用 `find -exec ... {} +`,这样不需要额外考虑结果如何传递。\n\n---\n\n## 15. Vim 面试够用版\n\n### 15.1 三种主要模式\n\n| 模式 | 进入方式 | 作用 |\n|---|---|---|\n| 普通模式 | 打开文件或按 `Esc` | 移动、复制、删除、搜索 |\n| 插入模式 | `i`、`a`、`o` 等 | 输入文字 |\n| 命令行模式 | 普通模式按 `:`、`/`、`?` | 保存、退出、搜索、替换 |\n\n```console\n[mia@linux ~]$ vim ~/linux-lab/app/config.env\n```\n\n最短操作流程:\n\n```text\ni 进入插入模式\n输入内容\nEsc 回到普通模式\n:wq 保存并退出\n```\n\n### 15.2 高频按键\n\n| 按键 | 作用 |\n|---|---|\n| `h j k l` | 左、下、上、右 |\n| `0` / ` 博客 | 行首/行尾 |\n| `gg` / `G` | 文件首/文件尾 |\n| `w` / `b` | 下一个/上一个单词 |\n| `i` / `a` | 光标前/后插入 |\n| `o` / `O` | 下方/上方新建一行 |\n| `dd` | 删除/剪切当前行 |\n| `yy` | 复制当前行 |\n| `p` | 粘贴到光标后 |\n| `u` | 撤销 |\n| `Ctrl+r` | 重做 |\n| `/word` | 向下搜索 |\n| `n` / `N` | 下一个/上一个匹配 |\n\n### 15.3 保存、退出与替换\n\n| 命令 | 作用 |\n|---|---|\n| `:w` | 保存 |\n| `:q` | 退出 |\n| `:wq` 或 `ZZ` | 保存并退出 |\n| `:q!` | 放弃修改并退出 |\n| `:set number` | 显示行号 |\n| `:%s/old/new/g` | 全文件替换 |\n| `:%s/old/new/gc` | 全文件替换,每次确认 |\n\n---\n\n## 16. 高频实战题\n\n### 16.1 统计日志中 ERROR 数量\n\n```console\n[mia@linux ~]$ grep -c 'ERROR' ~/linux-lab/logs/app.log\n2\n```\n\n若需要统计匹配结果行数,也可:\n\n```console\n$ grep 'ERROR' app.log | wc -l\n```\n\n### 16.2 找出 `/var/log` 下大于 100 MiB 的日志\n\n```console\n$ sudo find /var/log -type f -name '*.log' -size +100M -print\n```\n\n### 16.3 查找项目中写死的密码字段\n\n```console\n$ grep -RniE 'password|secret|token' ./project \\\n --exclude-dir=.git --exclude='*.pyc'\n```\n\n### 16.4 保留最近结果,同时记录错误\n\n```console\n$ python manage.py migrate \u003e migrate.log 2\u003e\u00261\n$ tail -n 30 migrate.log\n```\n\n### 16.5 把最近一天的 `.log` 文件归档到目录\n\n先只查看:\n\n```console\n$ find ./logs -type f -name '*.log' -mtime -1 -print\n```\n\n确认后再复制:\n\n```console\n$ mkdir -p backup/recent\n$ find ./logs -type f -name '*.log' -mtime -1 -exec cp -t backup/recent -- {} +\n```\n\n---\n\n## 17. 高频面试问答\n\n### 17.1 绝对路径和相对路径有什么区别?\n\n绝对路径从根目录 `/` 开始,不依赖当前目录;相对路径从当前工作目录开始,结果会受 `pwd` 影响。\n\n### 17.2 `\u003e` 和 `\u003e\u003e` 有什么区别?\n\n`\u003e` 覆盖目标文件,`\u003e\u003e` 追加到文件尾部。两者默认只处理标准输出,错误输出需要使用 `2\u003e` 等写法。\n\n### 17.3 管道和重定向有什么区别?\n\n管道把一个命令的标准输出交给另一个命令的标准输入;重定向改变标准输入、标准输出或标准错误所连接的位置,通常是文件。\n\n### 17.4 `find` 和 `grep` 的区别?\n\n`find` 主要按名称、类型、大小、时间等文件属性查找文件;`grep` 主要在文本内容中查找匹配行。两者经常组合使用。\n\n### 17.5 `which` 为什么找不到 `cd`?\n\n`cd` 通常是 Shell 内建命令,不是通过 `PATH` 搜索的普通外部程序。使用 `type cd` 能正确识别它。\n\n### 17.6 `tail -f` 与 `tail -F` 的区别?\n\n`-f` 持续读取当前文件描述符;`-F` 还会按文件名重试,日志轮转导致原文件被替换时更容易继续追踪。\n\n### 17.7 为什么 `rm -rf` 危险?\n\n`-r` 会递归遍历目录,`-f` 取消确认和多数报错。如果路径、变量或通配符写错,可能快速删除大量数据,而且通常无法从回收站恢复。\n\n### 17.8 单引号和双引号有什么区别?\n\n单引号基本保留全部字面内容,不展开变量和命令;双引号会展开 `$变量` 和 `$(命令)`,但保留空格并阻止通配展开。\n\n### 17.9 `2\u003e\u00261` 是什么意思?\n\n让文件描述符 2(标准错误)指向文件描述符 1(标准输出)当前指向的位置。它与前后重定向的顺序有关。\n\n### 17.10 如何统计出现次数最多的 IP?\n\n假设访问日志第一列是 IP:\n\n```console\n$ awk '{print $1}' access.log | sort | uniq -c | sort -nr | head\n```\n\n---\n\n## 18. 最终自测\n\n不看答案完成以下任务:\n\n1. 在家目录创建 `review/{src,logs,backup}`。\n2. 创建三行日志,其中两行包含 `ERROR`。\n3. 显示日志最后两行并持续跟踪。\n4. 统计 `ERROR` 行数。\n5. 把标准输出和错误同时保存到 `run.log`。\n6. 查找当前目录下 24 小时内修改的 `.py` 文件。\n7. 递归搜索项目中出现 `DEBUG=True` 的文件并显示行号。\n8. 用一条命令把查询结果同时显示并保存。\n9. 解释 `rm -rf \"$target\"` 中为什么变量必须加双引号,以及为什么执行前仍要验证目标。\n10. 在 Vim 中完成搜索、替换、保存退出。\n\n一组参考命令:\n\n```console\n$ mkdir -p ~/review/{src,logs,backup}\n$ printf 'INFO start\\nERROR db\\nERROR permission\\n' \u003e ~/review/logs/app.log\n$ tail -n 2 -f ~/review/logs/app.log\n$ grep -c 'ERROR' ~/review/logs/app.log\n$ command \u003e ~/review/run.log 2\u003e\u00261\n$ find . -type f -name '*.py' -mtime -1\n$ grep -RniF 'DEBUG=True' .\n$ grep -n 'ERROR' ~/review/logs/app.log | tee ~/review/backup/errors.txt\n```\n","content_html":"\u003ch1 id=\"linux-基础命令复习手册\"\u003eLinux 基础命令复习手册\u003c/h1\u003e\u003cblockquote\u003e\n\u003cp\u003e目标:能独立完成文件操作、内容检索、管道组合和日志查看,并能解释命令背后的工作方式。示例统一使用普通用户提示符 \u003ccode\u003e$\u003c/code\u003e;\u003ccode\u003e#\u003c/code\u003e 表示 root,复制命令时不要把提示符一起复制。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"1-高频命令总表\"\u003e1. 高频命令总表\u003c/h2\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e任务\u003c/th\u003e\n\u003cth\u003e首选命令\u003c/th\u003e\n\u003cth\u003e高频选项/写法\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e查看目录\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003els\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e-l\u003c/code\u003e、\u003ccode\u003e-a\u003c/code\u003e、\u003ccode\u003e-h\u003c/code\u003e、\u003ccode\u003e-t\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e切换/确认目录\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecd\u003c/code\u003e、\u003ccode\u003epwd\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecd ..\u003c/code\u003e、\u003ccode\u003ecd -\u003c/code\u003e、\u003ccode\u003ecd ~\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e创建目录/文件\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003emkdir\u003c/code\u003e、\u003ccode\u003etouch\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003emkdir -p\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查看文件\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecat\u003c/code\u003e、\u003ccode\u003eless\u003c/code\u003e、\u003ccode\u003ehead\u003c/code\u003e、\u003ccode\u003etail\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eless -N\u003c/code\u003e、\u003ccode\u003etail -f\u003c/code\u003e、\u003ccode\u003etail -F\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查看文件信息\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003efile\u003c/code\u003e、\u003ccode\u003estat\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003estat 文件\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e复制/移动\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecp\u003c/code\u003e、\u003ccode\u003emv\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecp -a\u003c/code\u003e、\u003ccode\u003ecp -r\u003c/code\u003e、\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e删除\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003erm\u003c/code\u003e、\u003ccode\u003ermdir\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003erm -r\u003c/code\u003e、\u003ccode\u003erm -i\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查找文件\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003efind\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e-name\u003c/code\u003e、\u003ccode\u003e-type\u003c/code\u003e、\u003ccode\u003e-size\u003c/code\u003e、\u003ccode\u003e-mtime\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查找命令\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etype\u003c/code\u003e、\u003ccode\u003ecommand -v\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etype -a\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e过滤内容\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003egrep\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e-n\u003c/code\u003e、\u003ccode\u003e-i\u003c/code\u003e、\u003ccode\u003e-r\u003c/code\u003e、\u003ccode\u003e-E\u003c/code\u003e、\u003ccode\u003e-v\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e统计内容\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ewc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e-l\u003c/code\u003e、\u003ccode\u003e-w\u003c/code\u003e、\u003ccode\u003e-c\u003c/code\u003e、\u003ccode\u003e-m\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e排序去重\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esort\u003c/code\u003e、\u003ccode\u003euniq\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esort -n\u003c/code\u003e、\u003ccode\u003esort -u\u003c/code\u003e、\u003ccode\u003euniq -c\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e提取列\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecut\u003c/code\u003e、\u003ccode\u003eawk\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecut -d: -f1\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e管道\u003c/td\u003e\n\u003ctd\u003e`\u003c/td\u003e\n\u003ctd\u003e`\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e重定向\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e\u0026gt;\u003c/code\u003e、\u003ccode\u003e\u0026gt;\u0026gt;\u003c/code\u003e、\u003ccode\u003e2\u0026gt;\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e覆盖、追加、重定向错误\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e同时看并保存\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etee\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e`命令\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e编辑文件\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003evim\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ei\u003c/code\u003e、\u003ccode\u003eEsc\u003c/code\u003e、\u003ccode\u003e:wq\u003c/code\u003e、\u003ccode\u003e:q!\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查帮助\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e--help\u003c/code\u003e、\u003ccode\u003eman\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eman 5 passwd\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003ch3 id=\"必须认识的目录\"\u003e必须认识的目录\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e目录\u003c/th\u003e\n\u003cth\u003e主要内容\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e整棵目录树的根\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/home\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e普通用户家目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/root\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eroot 的家目录,不是根目录 \u003ccode\u003e/\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/etc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e系统和服务配置\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/var\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e经常变化的数据,如日志、缓存、队列\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/var/log\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e常见日志目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/usr/bin\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e大量普通命令\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/usr/sbin\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e大量系统管理命令\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/tmp\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e临时文件,可能被系统清理\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/opt\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e可选的第三方软件\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/srv\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e服务对外提供的数据\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/dev\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e设备文件\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/proc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e内核和进程信息的虚拟文件系统\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/sys\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e设备与内核对象信息的虚拟文件系统\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003chr\u003e\n\u003ch2 id=\"2-先准备一套统一练习数据\"\u003e2. 先准备一套统一练习数据\u003c/h2\u003e\u003cp\u003e后面的命令都围绕 \u003ccode\u003e~/linux-lab\u003c/code\u003e 演示:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20mkdir%20-p%20~%2Flinux-lab%2F%7Bapp%2Cdata%2Clogs%2Cbackup%7D%0A%0A%5Bmia%40linux%20~%5D%24%20cat%20%3E%20~%2Flinux-lab%2Fdata%2Fusers.txt%20%3C%3C'EOF'%0A1001%20alice%20backend%20active%0A1002%20bob%20frontend%20active%0A1003%20carol%20backend%20disabled%0A1004%20dave%20ops%20active%0AEOF%0A%0A%5Bmia%40linux%20~%5D%24%20cat%20%3E%20~%2Flinux-lab%2Flogs%2Fapp.log%20%3C%3C'EOF'%0A2026-07-29%2009%3A00%3A01%20INFO%20%20server%20started%20port%3D8000%0A2026-07-29%2009%3A02%3A16%20INFO%20%20GET%20%2Fposts%20status%3D200%0A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A2026-07-29%2009%3A04%3A03%20WARN%20%20slow%20request%20cost%3D1.82s%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload%0AEOF%0A%0A%5Bmia%40linux%20~%5D%24%20printf%20'DEBUG%3Dfalse%5CnPORT%3D8000%5Cn'%20%3E%20~%2Flinux-lab%2Fapp%2Fconfig.env%0A%5Bmia%40linux%20~%5D%24%20touch%20~%2Flinux-lab%2Fapp%2Fmain.py\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ mkdir -p ~/linux-lab/{app,data,logs,backup}\n\n[mia@linux ~]$ cat \u0026gt; ~/linux-lab/data/users.txt \u0026lt;\u0026lt;'EOF'\n1001 alice backend active\n1002 bob frontend active\n1003 carol backend disabled\n1004 dave ops active\nEOF\n\n[mia@linux ~]$ cat \u0026gt; ~/linux-lab/logs/app.log \u0026lt;\u0026lt;'EOF'\n2026-07-29 09:00:01 INFO server started port=8000\n2026-07-29 09:02:16 INFO GET /posts status=200\n2026-07-29 09:03:40 ERROR database timeout request_id=r101\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\nEOF\n\n[mia@linux ~]$ printf 'DEBUG=false\\nPORT=8000\\n' \u0026gt; ~/linux-lab/app/config.env\n[mia@linux ~]$ touch ~/linux-lab/app/main.py\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e查看结构:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20find%20~%2Flinux-lab%20-maxdepth%202%20-printf%20'%25P%5Cn'%20%7C%20sort%0A%0Aapp%0Aapp%2Fconfig.env%0Aapp%2Fmain.py%0Abackup%0Adata%0Adata%2Fusers.txt%0Alogs%0Alogs%2Fapp.log\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ find ~/linux-lab -maxdepth 2 -printf '%P\\n' | sort\n\napp\napp/config.env\napp/main.py\nbackup\ndata\ndata/users.txt\nlogs\nlogs/app.log\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e开头出现的空行代表 \u003ccode\u003e~/linux-lab\u003c/code\u003e 本身;这是 \u003ccode\u003efind\u003c/code\u003e 的正常结果。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"3-linux-目录树与路径\"\u003e3. Linux 目录树与路径\u003c/h2\u003e\u003ch3 id=\"3-1-linux-只有一棵目录树\"\u003e3.1 Linux 只有一棵目录树\u003c/h3\u003e\u003cp\u003eWindows 常见 \u003ccode\u003eC:\\\u003c/code\u003e、\u003ccode\u003eD:\\\u003c/code\u003e 多个盘符;Linux 从唯一的根目录 \u003ccode\u003e/\u003c/code\u003e 开始。其他磁盘和文件系统通常被\u003cstrong\u003e挂载\u003c/strong\u003e到这棵树的某个目录。\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20etc%0A%E2%94%9C%E2%94%80%E2%94%80%20home%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20mia%0A%E2%94%9C%E2%94%80%E2%94%80%20usr%0A%E2%94%9C%E2%94%80%E2%94%80%20var%0A%E2%94%94%E2%94%80%E2%94%80%20...\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003e/\n├── etc\n├── home\n│ └── mia\n├── usr\n├── var\n└── ...\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"3-2-绝对路径与相对路径\"\u003e3.2 绝对路径与相对路径\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e路径\u003c/th\u003e\n\u003cth\u003e起点\u003c/th\u003e\n\u003cth\u003e示例\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e绝对路径\u003c/td\u003e\n\u003ctd\u003e根目录 \u003ccode\u003e/\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e/home/mia/linux-lab/logs/app.log\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e相对路径\u003c/td\u003e\n\u003ctd\u003e当前工作目录\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003elogs/app.log\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cd%20~%2Flinux-lab%0A%5Bmia%40linux%20linux-lab%5D%24%20pwd%0A%2Fhome%2Fmia%2Flinux-lab%0A%0A%5Bmia%40linux%20linux-lab%5D%24%20cat%20logs%2Fapp.log%0A2026-07-29%2009%3A00%3A01%20INFO%20%20server%20started%20port%3D8000%0A...%0A%0A%5Bmia%40linux%20linux-lab%5D%24%20cat%20%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A00%3A01%20INFO%20%20server%20started%20port%3D8000%0A...\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cd ~/linux-lab\n[mia@linux linux-lab]$ pwd\n/home/mia/linux-lab\n\n[mia@linux linux-lab]$ cat logs/app.log\n2026-07-29 09:00:01 INFO server started port=8000\n...\n\n[mia@linux linux-lab]$ cat /home/mia/linux-lab/logs/app.log\n2026-07-29 09:00:01 INFO server started port=8000\n...\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"3-3-特殊路径\"\u003e3.3 特殊路径\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e写法\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e.\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e当前目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e..\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e上一级目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e~\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e当前用户家目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e~alice\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e用户 alice 的家目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecd\u003c/code\u003e 中表示上一次所在目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20linux-lab%5D%24%20cd%20logs%0A%5Bmia%40linux%20logs%5D%24%20cd%20..%0A%5Bmia%40linux%20linux-lab%5D%24%20cd%20-%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%0A%5Bmia%40linux%20logs%5D%24%20cd%0A%5Bmia%40linux%20~%5D%24\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux linux-lab]$ cd logs\n[mia@linux logs]$ cd ..\n[mia@linux linux-lab]$ cd -\n/home/mia/linux-lab/logs\n[mia@linux logs]$ cd\n[mia@linux ~]$\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003ecd\u003c/code\u003e 不带参数等价于回到当前用户的家目录。\u003c/p\u003e\n\u003ch3 id=\"3-4-文件名-隐藏文件与大小写\"\u003e3.4 文件名、隐藏文件与大小写\u003c/h3\u003e\u003cul\u003e\n\u003cli\u003e以 \u003ccode\u003e.\u003c/code\u003e 开头的名称默认隐藏,例如 \u003ccode\u003e.bashrc\u003c/code\u003e。\u003c/li\u003e\n\u003cli\u003eLinux 文件名通常区分大小写:\u003ccode\u003eApp.py\u003c/code\u003e 与 \u003ccode\u003eapp.py\u003c/code\u003e 是两个名称。\u003c/li\u003e\n\u003cli\u003e扩展名不决定文件本质,\u003ccode\u003efile\u003c/code\u003e 会根据内容判断类型。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20ls%0Alinux-lab%0A%0A%5Bmia%40linux%20~%5D%24%20ls%20-a%0A.%20%20..%20%20.bashrc%20%20.ssh%20%20linux-lab%0A%0A%5Bmia%40linux%20~%5D%24%20file%20~%2Flinux-lab%2Flogs%2Fapp.log%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%3A%20ASCII%20text\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ ls\nlinux-lab\n\n[mia@linux ~]$ ls -a\n. .. .bashrc .ssh linux-lab\n\n[mia@linux ~]$ file ~/linux-lab/logs/app.log\n/home/mia/linux-lab/logs/app.log: ASCII text\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"4-命令的基本结构\"\u003e4. 命令的基本结构\u003c/h2\u003e\u003cp\u003e常见形式:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"command%20%5Boptions%5D%20%5Barguments%5D\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003ecommand [options] [arguments]\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20ls%20-lah%20~%2Flinux-lab\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ ls -lah ~/linux-lab\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\u003ccode\u003els\u003c/code\u003e:命令;\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e-l\u003c/code\u003e、\u003ccode\u003e-a\u003c/code\u003e、\u003ccode\u003e-h\u003c/code\u003e:选项;\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e~/linux-lab\u003c/code\u003e:参数。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e短选项常可合并,下面三种通常等价:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20ls%20-l%20-a%20-h%0A%24%20ls%20-lah%0A%24%20ls%20-hal\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003els\u003c/span\u003e -l -a -h\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003els\u003c/span\u003e -lah\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003els\u003c/span\u003e -hal\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e长选项通常以两个连字符开头:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20ls%20--all%20--human-readable\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003els\u003c/span\u003e --all --human-readable\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"4-1-如何查帮助\"\u003e4.1 如何查帮助\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20ls%20--help%20%7C%20head%0AUsage%3A%20ls%20%5BOPTION%5D...%20%5BFILE%5D...%0AList%20information%20about%20the%20FILEs%20...%0A%0A%5Bmia%40linux%20~%5D%24%20man%20ls%0ALS(1)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20User%20Commands%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20LS(1)\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ ls --help | head\nUsage: ls [OPTION]... [FILE]...\nList information about the FILEs ...\n\n[mia@linux ~]$ man ls\nLS(1) User Commands LS(1)\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e在 \u003ccode\u003eman\u003c/code\u003e 中:\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e按键\u003c/th\u003e\n\u003cth\u003e作用\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eSpace\u003c/code\u003e / \u003ccode\u003ePageDown\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下一页\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eb\u003c/code\u003e / \u003ccode\u003ePageUp\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e上一页\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/word\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e向下搜索\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003en\u003c/code\u003e / \u003ccode\u003eN\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下一个/上一个匹配\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eq\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e退出\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e手册分章节,例如:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20man%201%20passwd%20%20%20%20%23%20passwd%20%E5%91%BD%E4%BB%A4%0A%24%20man%205%20passwd%20%20%20%20%23%20%2Fetc%2Fpasswd%20%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003eman 1 passwd \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# passwd 命令\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003eman 5 passwd \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# /etc/passwd 文件格式\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"5-查看目录-ls\"\u003e5. 查看目录:\u003ccode\u003els\u003c/code\u003e\u003c/h2\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20ls%20-lah%20~%2Flinux-lab%0Atotal%200%0Adrwxr-xr-x%206%20mia%20mia%20%2059%20Jul%2029%2009%3A00%20.%0Adrwx------%208%20mia%20mia%20190%20Jul%2029%2008%3A50%20..%0Adrwxr-xr-x%202%20mia%20mia%20%2039%20Jul%2029%2009%3A00%20app%0Adrwxr-xr-x%202%20mia%20mia%20%20%206%20Jul%2029%2009%3A00%20backup%0Adrwxr-xr-x%202%20mia%20mia%20%2023%20Jul%2029%2009%3A00%20data%0Adrwxr-xr-x%202%20mia%20mia%20%2021%20Jul%2029%2009%3A00%20logs\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ ls -lah ~/linux-lab\ntotal 0\ndrwxr-xr-x 6 mia mia 59 Jul 29 09:00 .\ndrwx------ 8 mia mia 190 Jul 29 08:50 ..\ndrwxr-xr-x 2 mia mia 39 Jul 29 09:00 app\ndrwxr-xr-x 2 mia mia 6 Jul 29 09:00 backup\ndrwxr-xr-x 2 mia mia 23 Jul 29 09:00 data\ndrwxr-xr-x 2 mia mia 21 Jul 29 09:00 logs\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e常用选项:\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e选项\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-l\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e长格式\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-a\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e包括隐藏项\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-h\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e配合 \u003ccode\u003e-l\u003c/code\u003e,用 KiB、MiB、GiB 等易读单位\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-t\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e按修改时间排序\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-r\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e反向排序\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-d\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e查看目录本身,不列出目录内容\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示 inode 号\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e\u003ccode\u003els -l\u003c/code\u003e 一行大致包含:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"-rw-r--r--%201%20mia%20developers%20245%20Jul%2029%2009%3A05%20app.log%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%82%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%20%E5%90%8D%E7%A7%B0%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%82%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%E2%94%94%E2%94%80%20%E4%BF%AE%E6%94%B9%E6%97%B6%E9%97%B4%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%82%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%20%E5%A4%A7%E5%B0%8F%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%82%20%20%20%E2%94%94%E2%94%80%20%E6%89%80%E5%B1%9E%E7%BB%84%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%94%E2%94%80%20%E6%89%80%E5%B1%9E%E7%94%A8%E6%88%B7%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%20%E7%A1%AC%E9%93%BE%E6%8E%A5%E6%95%B0%0A%E2%94%94%E2%94%80%20%E6%96%87%E4%BB%B6%E7%B1%BB%E5%9E%8B%E4%B8%8E%E6%9D%83%E9%99%90\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003e-rw-r--r-- 1 mia developers 245 Jul 29 09:05 app.log\n│ │ │ │ │ │ └─ 名称\n│ │ │ │ │ └─ 修改时间\n│ │ │ │ └─ 大小\n│ │ │ └─ 所属组\n│ │ └─ 所属用户\n│ └─ 硬链接数\n└─ 文件类型与权限\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e不要用解析 \u003ccode\u003els\u003c/code\u003e 输出的方式编写严肃脚本;文件名可能包含空格、换行等特殊字符。脚本中更适合使用 \u003ccode\u003efind -print0\u003c/code\u003e 等安全接口。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"6-创建目录和文件\"\u003e6. 创建目录和文件\u003c/h2\u003e\u003ch3 id=\"6-1-mkdir\"\u003e6.1 \u003ccode\u003emkdir\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20mkdir%20~%2Fdemo%0A%0A%5Bmia%40linux%20~%5D%24%20mkdir%20~%2Fa%2Fb%2Fc%0Amkdir%3A%20cannot%20create%20directory%20%E2%80%98%2Fhome%2Fmia%2Fa%2Fb%2Fc%E2%80%99%3A%20No%20such%20file%20or%20directory%0A%0A%5Bmia%40linux%20~%5D%24%20mkdir%20-p%20~%2Fa%2Fb%2Fc%0A%5Bmia%40linux%20~%5D%24%20ls%20-d%20~%2Fa%2Fb%2Fc%0A%2Fhome%2Fmia%2Fa%2Fb%2Fc\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ mkdir ~/demo\n\n[mia@linux ~]$ mkdir ~/a/b/c\nmkdir: cannot create directory ‘/home/mia/a/b/c’: No such file or directory\n\n[mia@linux ~]$ mkdir -p ~/a/b/c\n[mia@linux ~]$ ls -d ~/a/b/c\n/home/mia/a/b/c\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e-p\u003c/code\u003e:父目录不存在时一起创建;目录已存在时不报错。\u003c/li\u003e\n\u003cli\u003e一次创建多个同级目录可用花括号展开:\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20mkdir%20-p%20project%2F%7Bsrc%2Ctests%2Cdocs%2Clogs%7D\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003emkdir\u003c/span\u003e -p project/{src,tests,docs,logs}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e花括号展开由 Shell 完成,不是 \u003ccode\u003emkdir\u003c/code\u003e 独有功能。\u003c/p\u003e\n\u003ch3 id=\"6-2-touch\"\u003e6.2 \u003ccode\u003etouch\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20touch%20notes.txt%0A%5Bmia%40linux%20~%5D%24%20ls%20-l%20notes.txt%0A-rw-r--r--%201%20mia%20mia%200%20Jul%2029%2010%3A12%20notes.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ touch notes.txt\n[mia@linux ~]$ ls -l notes.txt\n-rw-r--r-- 1 mia mia 0 Jul 29 10:12 notes.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003etouch\u003c/code\u003e 的准确作用是更新访问/修改时间;文件不存在时才会顺便创建空文件。\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20stat%20-c%20'%25y%20%25n'%20notes.txt%0A2026-07-29%2010%3A12%3A00.000000000%20-0700%20notes.txt%0A%0A%5Bmia%40linux%20~%5D%24%20touch%20notes.txt%0A%5Bmia%40linux%20~%5D%24%20stat%20-c%20'%25y%20%25n'%20notes.txt%0A2026-07-29%2010%3A15%3A34.000000000%20-0700%20notes.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ stat -c '%y %n' notes.txt\n2026-07-29 10:12:00.000000000 -0700 notes.txt\n\n[mia@linux ~]$ touch notes.txt\n[mia@linux ~]$ stat -c '%y %n' notes.txt\n2026-07-29 10:15:34.000000000 -0700 notes.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"6-3-file-与-stat\"\u003e6.3 \u003ccode\u003efile\u003c/code\u003e 与 \u003ccode\u003estat\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20file%20~%2Flinux-lab%2Fapp%2Fmain.py%0A%2Fhome%2Fmia%2Flinux-lab%2Fapp%2Fmain.py%3A%20empty%0A%0A%5Bmia%40linux%20~%5D%24%20stat%20~%2Flinux-lab%2Flogs%2Fapp.log%0A%20%20File%3A%20%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%0A%20%20Size%3A%20281%20%20%20%20%20%20%20%20Blocks%3A%208%20%20%20%20%20%20%20%20%20%20IO%20Block%3A%204096%20regular%20file%0AAccess%3A%20(0644%2F-rw-r--r--)%20%20Uid%3A%20(1000%2Fmia)%20%20%20Gid%3A%20(1000%2Fmia)\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ file ~/linux-lab/app/main.py\n/home/mia/linux-lab/app/main.py: empty\n\n[mia@linux ~]$ stat ~/linux-lab/logs/app.log\n File: /home/mia/linux-lab/logs/app.log\n Size: 281 Blocks: 8 IO Block: 4096 regular file\nAccess: (0644/-rw-r--r--) Uid: (1000/mia) Gid: (1000/mia)\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"7-查看文件内容\"\u003e7. 查看文件内容\u003c/h2\u003e\u003ch3 id=\"7-1-怎么选命令\"\u003e7.1 怎么选命令\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e场景\u003c/th\u003e\n\u003cth\u003e命令\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e小文件一次全部输出\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecat file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e大文件分页查看\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eless file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查看开头\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ehead file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查看结尾\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etail file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e持续跟踪日志\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etail -f file\u003c/code\u003e 或 \u003ccode\u003etail -F file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e带行号查看\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003enl -ba file\u003c/code\u003e 或 \u003ccode\u003eless -N file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003ch3 id=\"7-2-cat\"\u003e7.2 \u003ccode\u003ecat\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cat%20~%2Flinux-lab%2Fapp%2Fconfig.env%0ADEBUG%3Dfalse%0APORT%3D8000%0A%0A%5Bmia%40linux%20~%5D%24%20cat%20-n%20~%2Flinux-lab%2Fapp%2Fconfig.env%0A%20%20%20%20%201%20%20DEBUG%3Dfalse%0A%20%20%20%20%202%20%20PORT%3D8000\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cat ~/linux-lab/app/config.env\nDEBUG=false\nPORT=8000\n\n[mia@linux ~]$ cat -n ~/linux-lab/app/config.env\n 1 DEBUG=false\n 2 PORT=8000\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003ecat\u003c/code\u003e 还能连接多个文件:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20cat%20part1.txt%20part2.txt%20%3E%20all.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecat\u003c/span\u003e part1.txt part2.txt \u0026gt; all.txt\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"7-3-less\"\u003e7.3 \u003ccode\u003eless\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20less%20-N%20%2Fetc%2Fservices\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ less -N /etc/services\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e常用按键与 \u003ccode\u003eman\u003c/code\u003e 类似:\u003ccode\u003eSpace\u003c/code\u003e 翻页、\u003ccode\u003e/关键词\u003c/code\u003e 搜索、\u003ccode\u003en\u003c/code\u003e 下一个、\u003ccode\u003eq\u003c/code\u003e 退出。\u003ccode\u003eless\u003c/code\u003e 通常比 \u003ccode\u003emore\u003c/code\u003e 功能更完整。\u003c/p\u003e\n\u003ch3 id=\"7-4-head-与-tail\"\u003e7.4 \u003ccode\u003ehead\u003c/code\u003e 与 \u003ccode\u003etail\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20head%20-n%202%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A00%3A01%20INFO%20%20server%20started%20port%3D8000%0A2026-07-29%2009%3A02%3A16%20INFO%20%20GET%20%2Fposts%20status%3D200%0A%0A%5Bmia%40linux%20~%5D%24%20tail%20-n%202%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A04%3A03%20WARN%20%20slow%20request%20cost%3D1.82s%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ head -n 2 ~/linux-lab/logs/app.log\n2026-07-29 09:00:01 INFO server started port=8000\n2026-07-29 09:02:16 INFO GET /posts status=200\n\n[mia@linux ~]$ tail -n 2 ~/linux-lab/logs/app.log\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e持续追踪:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20tail%20-f%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ tail -f ~/linux-lab/logs/app.log\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e另一个终端追加内容:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20echo%20'2026-07-29%2009%3A08%3A11%20INFO%20%20worker%20ready'%20%3E%3E%20~%2Flinux-lab%2Flogs%2Fapp.log\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ echo '2026-07-29 09:08:11 INFO worker ready' \u0026gt;\u0026gt; ~/linux-lab/logs/app.log\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003etail -F\u003c/code\u003e 在日志轮转、文件被重新创建后会尝试继续跟踪,比 \u003ccode\u003e-f\u003c/code\u003e 更适合长期盯日志。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"8-复制-移动与删除\"\u003e8. 复制、移动与删除\u003c/h2\u003e\u003ch3 id=\"8-1-cp\"\u003e8.1 \u003ccode\u003ecp\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cp%20~%2Flinux-lab%2Fapp%2Fconfig.env%20~%2Flinux-lab%2Fbackup%2Fconfig.env.bak%0A%0A%5Bmia%40linux%20~%5D%24%20cp%20-r%20~%2Flinux-lab%2Fapp%20~%2Flinux-lab%2Fbackup%2F%0A%0A%5Bmia%40linux%20~%5D%24%20cp%20-a%20~%2Flinux-lab%2Fapp%20~%2Flinux-lab%2Fbackup%2Fapp-full\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cp ~/linux-lab/app/config.env ~/linux-lab/backup/config.env.bak\n\n[mia@linux ~]$ cp -r ~/linux-lab/app ~/linux-lab/backup/\n\n[mia@linux ~]$ cp -a ~/linux-lab/app ~/linux-lab/backup/app-full\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e选项\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-r\u003c/code\u003e / \u003ccode\u003e-R\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e递归复制目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-a\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e归档复制,尽量保留权限、时间、链接等属性\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e覆盖前询问\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-n\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e不覆盖已有目标\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-v\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示操作过程\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e复制多个源时,最后一个参数必须是已存在的目录:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20cp%20a.txt%20b.txt%20backup%2F\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecp\u003c/span\u003e a.txt b.txt backup/\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"8-2-mv\"\u003e8.2 \u003ccode\u003emv\u003c/code\u003e\u003c/h3\u003e\u003cp\u003e\u003ccode\u003emv\u003c/code\u003e 同时承担移动和重命名:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20mv%20old.txt%20new.txt%0A%0A%5Bmia%40linux%20~%5D%24%20mv%20new.txt%20~%2Flinux-lab%2Fbackup%2F\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ mv old.txt new.txt\n\n[mia@linux ~]$ mv new.txt ~/linux-lab/backup/\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e目标不存在:通常表示重命名。\u003c/li\u003e\n\u003cli\u003e目标是已存在的目录:移动到该目录内。\u003c/li\u003e\n\u003cli\u003e同一文件系统内移动通常只修改目录项,很快;跨文件系统时可能变成复制后删除。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"8-3-rm\"\u003e8.3 \u003ccode\u003erm\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20rm%20old.log%0A%5Bmia%40linux%20~%5D%24%20rm%20-r%20old-directory%0A%5Bmia%40linux%20~%5D%24%20rm%20-i%20important.conf%0Arm%3A%20remove%20regular%20file%20'important.conf'%3F%20n\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ rm old.log\n[mia@linux ~]$ rm -r old-directory\n[mia@linux ~]$ rm -i important.conf\nrm: remove regular file 'important.conf'? n\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e选项\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-r\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e递归删除目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-f\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e强制,不询问并忽略不存在的文件\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e每次删除前询问\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-I\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e大量删除或递归删除前询问一次\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e\u003ccode\u003erm\u003c/code\u003e 默认是否询问与别名和选项有关,不是简单按“普通用户/root”区分。\u003c/p\u003e\n\u003ch3 id=\"8-4-删除前的安全习惯\"\u003e8.4 删除前的安全习惯\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%23%201.%20%E5%85%88%E6%89%93%E5%8D%B0%E7%9B%AE%E6%A0%87%0A%5Bmia%40linux%20logs%5D%24%20printf%20'%3C%25s%3E%5Cn'%20*.log%0A%3Capp.log%3E%0A%3Cold.log%3E%0A%0A%23%202.%20%E5%86%8D%E5%88%A0%E9%99%A4%EF%BC%8C%E5%B9%B6%E8%AE%A9%E5%8D%B1%E9%99%A9%E6%93%8D%E4%BD%9C%E8%AF%A2%E9%97%AE%E4%B8%80%E6%AC%A1%0A%5Bmia%40linux%20logs%5D%24%20rm%20-I%20--%20*.log%0Arm%3A%20remove%202%20arguments%3F%20n\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e# \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e1. 先打印目标\u003c/span\u003e\n[mia@linux logs]$ printf '\u0026lt;%s\u0026gt;\\n' *.log\n\u0026lt;app.log\u0026gt;\n\u0026lt;old.log\u0026gt;\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e\n# \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e2. 再删除,并让危险操作询问一次\u003c/span\u003e\n[mia@linux logs]$ rm -I -- *.log\nrm: remove 2 arguments? n\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e先用 \u003ccode\u003epwd\u003c/code\u003e、\u003ccode\u003els\u003c/code\u003e 或 \u003ccode\u003eprintf\u003c/code\u003e 确认当前目录和通配结果。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e--\u003c/code\u003e 表示选项结束,可安全处理名称以 \u003ccode\u003e-\u003c/code\u003e 开头的文件。\u003c/li\u003e\n\u003cli\u003e不要执行 \u003ccode\u003erm -rf /\u003c/code\u003e、\u003ccode\u003erm -rf /*\u003c/code\u003e 或目标变量未经检查的递归删除。\u003c/li\u003e\n\u003cli\u003e命令行 \u003ccode\u003erm\u003c/code\u003e 通常不经过回收站。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e删除空目录可用:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20rmdir%20empty-directory\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ermdir\u003c/span\u003e empty-directory\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"9-通配符-引号与命令替换\"\u003e9. 通配符、引号与命令替换\u003c/h2\u003e\u003ch3 id=\"9-1-通配符\"\u003e9.1 通配符\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e写法\u003c/th\u003e\n\u003cth\u003e匹配\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e*\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e任意长度字符,通常不跨 \u003ccode\u003e/\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e任意一个字符\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e[abc]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ea\u003c/code\u003e、\u003ccode\u003eb\u003c/code\u003e、\u003ccode\u003ec\u003c/code\u003e 中任一个\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e[0-9]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e任一个数字\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e[!0-9]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e任一个非数字字符\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20logs%5D%24%20printf%20'%25s%5Cn'%20*.log%0Aapp.log%0Aold.log%0A%0A%5Bmia%40linux%20data%5D%24%20printf%20'%25s%5Cn'%20user%3F.txt%0Auser1.txt%0Auser2.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux logs]$ printf '%s\\n' *.log\napp.log\nold.log\n\n[mia@linux data]$ printf '%s\\n' user?.txt\nuser1.txt\nuser2.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e通配符一般先由 Shell 展开,再把结果交给命令。\u003c/p\u003e\n\u003ch3 id=\"9-2-单引号-双引号与不加引号\"\u003e9.2 单引号、双引号与不加引号\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20name%3D'Linux'%0A%0A%5Bmia%40linux%20~%5D%24%20echo%20'%24name'%0A%24name%0A%0A%5Bmia%40linux%20~%5D%24%20echo%20%22%24name%22%0ALinux%0A%0A%5Bmia%40linux%20~%5D%24%20echo%20*.txt%0Anotes.txt%20report.txt%0A%0A%5Bmia%40linux%20~%5D%24%20echo%20%22*.txt%22%0A*.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ name='Linux'\n\n[mia@linux ~]$ echo '$name'\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$\u003c/span\u003e\u003cspan class=\"language-bash\"\u003ename\u003c/span\u003e\n\n[mia@linux ~]$ echo \"$name\"\nLinux\n\n[mia@linux ~]$ echo *.txt\nnotes.txt report.txt\n\n[mia@linux ~]$ echo \"*.txt\"\n*.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e写法\u003c/th\u003e\n\u003cth align=\"right\"\u003e变量展开\u003c/th\u003e\n\u003cth align=\"right\"\u003e命令替换\u003c/th\u003e\n\u003cth align=\"right\"\u003e通配展开\u003c/th\u003e\n\u003cth align=\"right\"\u003e保留空格\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e不加引号\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e\"双引号\"\u003c/code\u003e\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e'单引号'\u003c/code\u003e\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e变量引用通常写成 \u003ccode\u003e\"$var\"\u003c/code\u003e,避免空格和通配符造成意外拆分。\u003c/p\u003e\n\u003ch3 id=\"9-3-命令替换\"\u003e9.3 命令替换\u003c/h3\u003e\u003cp\u003e推荐使用 \u003ccode\u003e$(...)\u003c/code\u003e,可读性和嵌套性优于旧式反引号:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20echo%20%22%E5%BD%93%E5%89%8D%E7%9B%AE%E5%BD%95%EF%BC%9A%24(pwd)%22%0A%E5%BD%93%E5%89%8D%E7%9B%AE%E5%BD%95%EF%BC%9A%2Fhome%2Fmia%0A%0A%5Bmia%40linux%20~%5D%24%20today%3D%24(date%20%2B%25F)%0A%5Bmia%40linux%20~%5D%24%20echo%20%22%24today%22%0A2026-07-29\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ echo \"当前目录:$(pwd)\"\n当前目录:/home/mia\n\n[mia@linux ~]$ today=$(date +%F)\n[mia@linux ~]$ echo \"$today\"\n2026-07-29\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"10-查找命令与文件\"\u003e10. 查找命令与文件\u003c/h2\u003e\u003ch3 id=\"10-1-type-command-v-which\"\u003e10.1 \u003ccode\u003etype\u003c/code\u003e、\u003ccode\u003ecommand -v\u003c/code\u003e、\u003ccode\u003ewhich\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20type%20cd%0Acd%20is%20a%20shell%20builtin%0A%0A%5Bmia%40linux%20~%5D%24%20type%20-a%20python%0Apython%20is%20%2Fhome%2Fmia%2Fvenv%2Fbin%2Fpython%0Apython%20is%20%2Fusr%2Fbin%2Fpython%0A%0A%5Bmia%40linux%20~%5D%24%20command%20-v%20grep%0A%2Fusr%2Fbin%2Fgrep\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ type cd\ncd is a shell builtin\n\n[mia@linux ~]$ type -a python\npython is /home/mia/venv/bin/python\npython is /usr/bin/python\n\n[mia@linux ~]$ command -v grep\n/usr/bin/grep\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\u003ccode\u003etype\u003c/code\u003e 能识别别名、函数、Shell 内建和外部命令。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecommand -v\u003c/code\u003e 适合脚本判断命令是否存在。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ewhich\u003c/code\u003e 主要搜索 \u003ccode\u003ePATH\u003c/code\u003e 中的可执行文件,对别名和内建命令不一定可靠。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"10-2-find-基本结构\"\u003e10.2 \u003ccode\u003efind\u003c/code\u003e 基本结构\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"find%20%E6%90%9C%E7%B4%A2%E8%B5%B7%E7%82%B9%20%E6%9D%A1%E4%BB%B6%20%E5%8A%A8%E4%BD%9C\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003efind 搜索起点 条件 动作\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e按名称:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20find%20~%2Flinux-lab%20-name%20'app.log'%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%0A%0A%5Bmia%40linux%20~%5D%24%20find%20~%2Flinux-lab%20-iname%20'*.ENV'%0A%2Fhome%2Fmia%2Flinux-lab%2Fapp%2Fconfig.env\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ find ~/linux-lab -name 'app.log'\n/home/mia/linux-lab/logs/app.log\n\n[mia@linux ~]$ find ~/linux-lab -iname '*.ENV'\n/home/mia/linux-lab/app/config.env\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e通配模式要加引号,避免被当前 Shell 提前展开。\u003c/p\u003e\n\u003cp\u003e按类型:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20~%2Flinux-lab%20-type%20f%20%20%20%20%20%23%20%E6%99%AE%E9%80%9A%E6%96%87%E4%BB%B6%0A%24%20find%20~%2Flinux-lab%20-type%20d%20%20%20%20%20%23%20%E7%9B%AE%E5%BD%95%0A%24%20find%20~%2Flinux-lab%20-type%20l%20%20%20%20%20%23%20%E7%AC%A6%E5%8F%B7%E9%93%BE%E6%8E%A5\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ~/linux-lab -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 普通文件\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ~/linux-lab -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e d \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 目录\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ~/linux-lab -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e l \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 符号链接\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e按大小:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20%2Fvar%2Flog%20-type%20f%20-size%20%2B100M%0A%24%20find%20.%20-type%20f%20-size%20-10k\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind /var/log -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -size +100M\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -size -10k\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e按修改时间:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20.%20-type%20f%20-mtime%20-1%20%20%20%20%20%23%20%E7%BA%A6%2024%20%E5%B0%8F%E6%97%B6%E5%86%85%E4%BF%AE%E6%94%B9%0A%24%20find%20.%20-type%20f%20-mtime%20%2B30%20%20%20%20%23%20%E8%B6%85%E8%BF%87%E7%BA%A6%2030%20%E5%A4%A9%0A%24%20find%20.%20-type%20f%20-mmin%20-10%20%20%20%20%20%23%20%E7%BA%A6%2010%20%E5%88%86%E9%92%9F%E5%86%85%E4%BF%AE%E6%94%B9\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -mtime -1 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 约 24 小时内修改\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -mtime +30 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 超过约 30 天\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -mmin -10 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 约 10 分钟内修改\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e组合条件:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20.%20-type%20f%20%5C(%20-name%20'*.log'%20-o%20-name%20'*.txt'%20%5C)%0A%24%20find%20.%20-type%20f%20-name%20'*.log'%20!%20-name%20'debug.log'\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f \\( -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -o -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.txt'\u003c/span\u003e \\)\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e ! -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'debug.log'\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e对结果执行命令:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20find%20~%2Flinux-lab%2Flogs%20-type%20f%20-name%20'*.log'%20%5C%0A%3E%20-exec%20grep%20-Hn%20'ERROR'%20%7B%7D%20%2B%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%3A3%3A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%3A5%3A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ find ~/linux-lab/logs -type f -name '*.log' \\\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e\u0026gt; \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e-\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eexec\u003c/span\u003e grep -Hn \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e {} +\u003c/span\u003e\n/home/mia/linux-lab/logs/app.log:3:2026-07-29 09:03:40 ERROR database timeout request_id=r101\n/home/mia/linux-lab/logs/app.log:5:2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003e{} +\u003c/code\u003e 会把多个结果成批传给命令,通常比每个文件执行一次的 \u003ccode\u003e{} \\;\u003c/code\u003e 更高效。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"11-文本过滤与统计\"\u003e11. 文本过滤与统计\u003c/h2\u003e\u003ch3 id=\"11-1-grep\"\u003e11.1 \u003ccode\u003egrep\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20-n%20'ERROR'%20~%2Flinux-lab%2Flogs%2Fapp.log%0A3%3A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A5%3A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep -n 'ERROR' ~/linux-lab/logs/app.log\n3:2026-07-29 09:03:40 ERROR database timeout request_id=r101\n5:2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e常用选项:\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e选项\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-n\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示行号\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e忽略大小写\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-v\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e反选,不含匹配内容\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-r\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e递归搜索目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-l\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e只显示匹配到的文件名\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-c\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示每个文件的匹配行数\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-E\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e使用扩展正则表达式\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-F\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e把模式当普通字符串,不解释正则符号\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-A 2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示匹配行及后 2 行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-B 2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示匹配行及前 2 行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-C 2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示匹配行前后各 2 行\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20-E%20'ERROR%7CWARN'%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A2026-07-29%2009%3A04%3A03%20WARN%20%20slow%20request%20cost%3D1.82s%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload%0A%0A%5Bmia%40linux%20~%5D%24%20grep%20-rln%20'DEBUG%3Dfalse'%20~%2Flinux-lab%0A%2Fhome%2Fmia%2Flinux-lab%2Fapp%2Fconfig.env\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep -E 'ERROR|WARN' ~/linux-lab/logs/app.log\n2026-07-29 09:03:40 ERROR database timeout request_id=r101\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\n\n[mia@linux ~]$ grep -rln 'DEBUG=false' ~/linux-lab\n/home/mia/linux-lab/app/config.env\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"11-2-wc\"\u003e11.2 \u003ccode\u003ewc\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20wc%20~%2Flinux-lab%2Fdata%2Fusers.txt%0A%20%204%20%2016%20105%20%2Fhome%2Fmia%2Flinux-lab%2Fdata%2Fusers.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ wc ~/linux-lab/data/users.txt\n 4 16 105 /home/mia/linux-lab/data/users.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e默认依次显示行数、单词数、字节数。\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20wc%20-l%20file%20%20%20%20%20%20%20%23%20%E8%A1%8C%E6%95%B0%0A%24%20wc%20-w%20file%20%20%20%20%20%20%20%23%20%E5%8D%95%E8%AF%8D%E6%95%B0%0A%24%20wc%20-c%20file%20%20%20%20%20%20%20%23%20%E5%AD%97%E8%8A%82%E6%95%B0%0A%24%20wc%20-m%20file%20%20%20%20%20%20%20%23%20%E5%AD%97%E7%AC%A6%E6%95%B0\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -l file \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 行数\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -w file \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 单词数\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -c file \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 字节数\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -m file \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 字符数\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003eUTF-8 中文字符通常占多个字节,因此 \u003ccode\u003e-c\u003c/code\u003e 与 \u003ccode\u003e-m\u003c/code\u003e 可能不同。\u003c/p\u003e\n\u003ch3 id=\"11-3-sort-uniq-cut\"\u003e11.3 \u003ccode\u003esort\u003c/code\u003e、\u003ccode\u003euniq\u003c/code\u003e、\u003ccode\u003ecut\u003c/code\u003e\u003c/h3\u003e\u003cp\u003e统计每种状态的人数:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20awk%20'%7Bprint%20%244%7D'%20~%2Flinux-lab%2Fdata%2Fusers.txt%20%7C%20sort%20%7C%20uniq%20-c%0A%20%20%20%20%20%203%20active%0A%20%20%20%20%20%201%20disabled\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ awk '{print $4}' ~/linux-lab/data/users.txt | sort | uniq -c\n 3 active\n 1 disabled\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003euniq\u003c/code\u003e 只合并\u003cstrong\u003e相邻\u003c/strong\u003e重复行,所以一般先 \u003ccode\u003esort\u003c/code\u003e。\u003c/p\u003e\n\u003cp\u003e从 \u003ccode\u003e/etc/passwd\u003c/code\u003e 提取用户名和登录 Shell:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cut%20-d%3A%20-f1%2C7%20%2Fetc%2Fpasswd%20%7C%20head%0Aroot%3A%2Fbin%2Fbash%0Abin%3A%2Fsbin%2Fnologin%0Adaemon%3A%2Fsbin%2Fnologin%0A...\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cut -d: -f1,7 /etc/passwd | head\nroot:/bin/bash\nbin:/sbin/nologin\ndaemon:/sbin/nologin\n...\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"12-管道与重定向\"\u003e12. 管道与重定向\u003c/h2\u003e\u003ch3 id=\"12-1-三个标准流\"\u003e12.1 三个标准流\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth align=\"right\"\u003e编号\u003c/th\u003e\n\u003cth\u003e名称\u003c/th\u003e\n\u003cth\u003e默认位置\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd align=\"right\"\u003e\u003ccode\u003e0\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e标准输入 stdin\u003c/td\u003e\n\u003ctd\u003e键盘\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd align=\"right\"\u003e\u003ccode\u003e1\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e标准输出 stdout\u003c/td\u003e\n\u003ctd\u003e终端\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd align=\"right\"\u003e\u003ccode\u003e2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e标准错误 stderr\u003c/td\u003e\n\u003ctd\u003e终端\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003ch3 id=\"12-2-管道\"\u003e12.2 管道 \u003ccode\u003e|\u003c/code\u003e\u003c/h3\u003e\u003cp\u003e管道把左侧命令的\u003cstrong\u003e标准输出\u003c/strong\u003e交给右侧命令的\u003cstrong\u003e标准输入\u003c/strong\u003e:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20'ERROR'%20~%2Flinux-lab%2Flogs%2Fapp.log%20%7C%20wc%20-l%0A2%0A%0A%5Bmia%40linux%20~%5D%24%20ps%20-ef%20%7C%20grep%20'%5Bg%5Dunicorn'%0Amia%20%20%20%20%20%20%203184%20%20%20%20%20%20%201%20%200%2009%3A00%20%3F%20%2000%3A00%3A01%20gunicorn%3A%20master%20%5Bconfig.wsgi%5D\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep 'ERROR' ~/linux-lab/logs/app.log | wc -l\n2\n\n[mia@linux ~]$ ps -ef | grep '[g]unicorn'\nmia 3184 1 0 09:00 ? 00:00:01 gunicorn: master [config.wsgi]\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003egrep '[g]unicorn'\u003c/code\u003e 可以避免把当前 \u003ccode\u003egrep gunicorn\u003c/code\u003e 自己匹配出来。更直接的做法是:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20pgrep%20-af%20gunicorn\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003epgrep -af gunicorn\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e管道默认不传递标准错误:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20%2F%20-name%20'*.conf'%202%3E%2Fdev%2Fnull%20%7C%20head\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind / -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.conf'\u003c/span\u003e 2\u0026gt;/dev/null | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ehead\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"12-3-输出重定向\"\u003e12.3 输出重定向\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20echo%20'DEBUG%3Dfalse'%20%3E%20config.env%20%20%20%20%20%20%20%23%20%E8%A6%86%E7%9B%96%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA%0A%24%20echo%20'PORT%3D8000'%20%3E%3E%20config.env%20%20%20%20%20%20%20%20%23%20%E8%BF%BD%E5%8A%A0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA%0A%24%20command%202%3E%20error.log%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E5%8F%AA%E9%87%8D%E5%AE%9A%E5%90%91%E9%94%99%E8%AF%AF%0A%24%20command%20%3E%20output.log%202%3E%20error.log%20%20%20%20%20%23%20%E8%BE%93%E5%87%BA%E5%92%8C%E9%94%99%E8%AF%AF%E5%88%86%E5%BC%80%0A%24%20command%20%3E%20all.log%202%3E%261%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E4%BA%8C%E8%80%85%E5%86%99%E5%85%A5%E5%90%8C%E4%B8%80%E6%96%87%E4%BB%B6%0A%24%20command%20%26%3E%20all.log%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20Bash%20%E7%AE%80%E5%86%99%0A%24%20command%20%3E%20%2Fdev%2Fnull%202%3E%261%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E4%B8%A2%E5%BC%83%E8%BE%93%E5%87%BA%E4%B8%8E%E9%94%99%E8%AF%AF\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eecho\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'DEBUG=false'\u003c/span\u003e \u0026gt; config.env \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 覆盖标准输出\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eecho\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'PORT=8000'\u003c/span\u003e \u0026gt;\u0026gt; config.env \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 追加标准输出\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e 2\u0026gt; error.log \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 只重定向错误\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; output.log 2\u0026gt; error.log \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 输出和错误分开\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; all.log 2\u0026gt;\u0026amp;1 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 二者写入同一文件\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026amp;\u0026gt; all.log \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# Bash 简写\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 丢弃输出与错误\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e顺序很重要:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20command%20%3E%20all.log%202%3E%261%20%20%20%20%23%20stderr%20%E8%B7%9F%E9%9A%8F%E5%B7%B2%E7%BB%8F%E6%8C%87%E5%90%91%20all.log%20%E7%9A%84%20stdout%0A%24%20command%202%3E%261%20%3E%20all.log%20%20%20%20%23%20stderr%20%E5%85%88%E6%8C%87%E5%90%91%E7%BB%88%E7%AB%AF%EF%BC%8C%E4%B9%8B%E5%90%8E%E5%8F%AA%E6%9C%89%20stdout%20%E6%94%B9%E5%88%B0%E6%96%87%E4%BB%B6\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; all.log 2\u0026gt;\u0026amp;1 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# stderr 跟随已经指向 all.log 的 stdout\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e 2\u0026gt;\u0026amp;1 \u0026gt; all.log \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# stderr 先指向终端,之后只有 stdout 改到文件\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"12-4-输入重定向与-here-document\"\u003e12.4 输入重定向与 Here Document\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20wc%20-l%20%3C%20users.txt%0A4\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -l \u0026lt; users.txt\u003c/span\u003e\n4\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e批量写入多行文本:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cat%20%3E%20settings.ini%20%3C%3C'EOF'%0A%5Bapp%5D%0Adebug%20%3D%20false%0Aport%20%3D%208000%0AEOF\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cat \u0026gt; settings.ini \u0026lt;\u0026lt;'EOF'\n[app]\ndebug = false\nport = 8000\nEOF\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e分隔符加单引号后,正文中的 \u003ccode\u003e$变量\u003c/code\u003e 和 \u003ccode\u003e$(命令)\u003c/code\u003e 不会展开。\u003c/p\u003e\n\u003ch3 id=\"12-5-tee\"\u003e12.5 \u003ccode\u003etee\u003c/code\u003e\u003c/h3\u003e\u003cp\u003e既在屏幕显示又保存:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20-E%20'ERROR%7CWARN'%20~%2Flinux-lab%2Flogs%2Fapp.log%20%7C%20tee%20~%2Flinux-lab%2Fbackup%2Fproblems.log%0A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A2026-07-29%2009%3A04%3A03%20WARN%20%20slow%20request%20cost%3D1.82s%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep -E 'ERROR|WARN' ~/linux-lab/logs/app.log | tee ~/linux-lab/backup/problems.log\n2026-07-29 09:03:40 ERROR database timeout request_id=r101\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e追加使用 \u003ccode\u003etee -a\u003c/code\u003e。写入需要 root 权限的文件时:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20echo%20'127.0.0.1%20forum.local'%20%7C%20sudo%20tee%20-a%20%2Fetc%2Fhosts\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eecho\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'127.0.0.1 forum.local'\u003c/span\u003e | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003esudo\u003c/span\u003e \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etee\u003c/span\u003e -a /etc/hosts\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003esudo echo ... \u0026gt; /etc/hosts\u003c/code\u003e 往往失败,因为重定向由当前普通 Shell 提前完成,\u003ccode\u003esudo\u003c/code\u003e 只作用于 \u003ccode\u003eecho\u003c/code\u003e。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"13-命令连接与退出状态\"\u003e13. 命令连接与退出状态\u003c/h2\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e写法\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecmd1 ; cmd2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e无论前者成功与否都执行后者\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecmd1 \u0026amp;\u0026amp; cmd2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e前者成功才执行后者\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e`cmd1\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecmd1 | cmd2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e前者输出作为后者输入\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20mkdir%20release%20%26%26%20cp%20app.py%20release%2F%0A%0A%5Bmia%40linux%20~%5D%24%20test%20-f%20config.env%20%7C%7C%20echo%20'config.env%20%E4%B8%8D%E5%AD%98%E5%9C%A8'%0Aconfig.env%20%E4%B8%8D%E5%AD%98%E5%9C%A8\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ mkdir release \u0026amp;\u0026amp; cp app.py release/\n\n[mia@linux ~]$ test -f config.env || echo 'config.env 不存在'\nconfig.env 不存在\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003eLinux 命令通常用退出状态表示结果:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e0\u003c/code\u003e:成功;\u003c/li\u003e\n\u003cli\u003e非 \u003ccode\u003e0\u003c/code\u003e:失败或出现特定情况。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20'ERROR'%20~%2Flinux-lab%2Flogs%2Fapp.log%20%3E%2Fdev%2Fnull%0A%5Bmia%40linux%20~%5D%24%20echo%20%24%3F%0A0%0A%0A%5Bmia%40linux%20~%5D%24%20grep%20'FATAL'%20~%2Flinux-lab%2Flogs%2Fapp.log%20%3E%2Fdev%2Fnull%0A%5Bmia%40linux%20~%5D%24%20echo%20%24%3F%0A1\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep 'ERROR' ~/linux-lab/logs/app.log \u0026gt;/dev/null\n[mia@linux ~]$ echo $?\n0\n\n[mia@linux ~]$ grep 'FATAL' ~/linux-lab/logs/app.log \u0026gt;/dev/null\n[mia@linux ~]$ echo $?\n1\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003e$?\u003c/code\u003e 只保存最近一条前台命令的状态,应立即查看。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"14-安全地批量处理文件-xargs\"\u003e14. 安全地批量处理文件:\u003ccode\u003exargs\u003c/code\u003e\u003c/h2\u003e\u003cp\u003e简单形式:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20printf%20'%25s%5Cn'%20a.log%20b.log%20%7C%20xargs%20rm\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eprintf\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'%s\\n'\u003c/span\u003e a.log b.log | xargs \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003erm\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e但文件名可能包含空格或换行,严肃场景使用 NUL 分隔:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20logs%20-type%20f%20-name%20'*.log'%20-print0%20%7C%20xargs%20-0%20grep%20-Hn%20'ERROR'\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind logs -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -print0 | xargs -0 grep -Hn \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e许多场景可直接用 \u003ccode\u003efind -exec ... {} +\u003c/code\u003e,这样不需要额外考虑结果如何传递。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"15-vim-面试够用版\"\u003e15. Vim 面试够用版\u003c/h2\u003e\u003ch3 id=\"15-1-三种主要模式\"\u003e15.1 三种主要模式\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e模式\u003c/th\u003e\n\u003cth\u003e进入方式\u003c/th\u003e\n\u003cth\u003e作用\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e普通模式\u003c/td\u003e\n\u003ctd\u003e打开文件或按 \u003ccode\u003eEsc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e移动、复制、删除、搜索\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e插入模式\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ei\u003c/code\u003e、\u003ccode\u003ea\u003c/code\u003e、\u003ccode\u003eo\u003c/code\u003e 等\u003c/td\u003e\n\u003ctd\u003e输入文字\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e命令行模式\u003c/td\u003e\n\u003ctd\u003e普通模式按 \u003ccode\u003e:\u003c/code\u003e、\u003ccode\u003e/\u003c/code\u003e、\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e保存、退出、搜索、替换\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20vim%20~%2Flinux-lab%2Fapp%2Fconfig.env\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ vim ~/linux-lab/app/config.env\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e最短操作流程:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"i%20%20%20%20%20%20%20%20%E8%BF%9B%E5%85%A5%E6%8F%92%E5%85%A5%E6%A8%A1%E5%BC%8F%0A%E8%BE%93%E5%85%A5%E5%86%85%E5%AE%B9%0AEsc%20%20%20%20%20%20%E5%9B%9E%E5%88%B0%E6%99%AE%E9%80%9A%E6%A8%A1%E5%BC%8F%0A%3Awq%20%20%20%20%20%20%E4%BF%9D%E5%AD%98%E5%B9%B6%E9%80%80%E5%87%BA\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003ei 进入插入模式\n输入内容\nEsc 回到普通模式\n:wq 保存并退出\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"15-2-高频按键\"\u003e15.2 高频按键\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e按键\u003c/th\u003e\n\u003cth\u003e作用\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eh j k l\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e左、下、上、右\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e0\u003c/code\u003e / \u003ccode\u003e$\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e行首/行尾\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003egg\u003c/code\u003e / \u003ccode\u003eG\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e文件首/文件尾\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ew\u003c/code\u003e / \u003ccode\u003eb\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下一个/上一个单词\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ei\u003c/code\u003e / \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e光标前/后插入\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eo\u003c/code\u003e / \u003ccode\u003eO\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下方/上方新建一行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edd\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e删除/剪切当前行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eyy\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e复制当前行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ep\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e粘贴到光标后\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eu\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e撤销\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eCtrl+r\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e重做\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/word\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e向下搜索\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003en\u003c/code\u003e / \u003ccode\u003eN\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下一个/上一个匹配\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003ch3 id=\"15-3-保存-退出与替换\"\u003e15.3 保存、退出与替换\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e命令\u003c/th\u003e\n\u003cth\u003e作用\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:w\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e保存\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:q\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e退出\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:wq\u003c/code\u003e 或 \u003ccode\u003eZZ\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e保存并退出\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:q!\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e放弃修改并退出\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:set number\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示行号\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:%s/old/new/g\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e全文件替换\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:%s/old/new/gc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e全文件替换,每次确认\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003chr\u003e\n\u003ch2 id=\"16-高频实战题\"\u003e16. 高频实战题\u003c/h2\u003e\u003ch3 id=\"16-1-统计日志中-error-数量\"\u003e16.1 统计日志中 ERROR 数量\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20-c%20'ERROR'%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep -c 'ERROR' ~/linux-lab/logs/app.log\n2\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e若需要统计匹配结果行数,也可:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20grep%20'ERROR'%20app.log%20%7C%20wc%20-l\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e app.log | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -l\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"16-2-找出-var-log-下大于-100-mib-的日志\"\u003e16.2 找出 \u003ccode\u003e/var/log\u003c/code\u003e 下大于 100 MiB 的日志\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20sudo%20find%20%2Fvar%2Flog%20-type%20f%20-name%20'*.log'%20-size%20%2B100M%20-print\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003esudo\u003c/span\u003e find /var/log -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -size +100M -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eprint\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"16-3-查找项目中写死的密码字段\"\u003e16.3 查找项目中写死的密码字段\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20grep%20-RniE%20'password%7Csecret%7Ctoken'%20.%2Fproject%20%5C%0A%20%20--exclude-dir%3D.git%20--exclude%3D'*.pyc'\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep -RniE \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'password|secret|token'\u003c/span\u003e ./project \\\n --exclude-dir=.git --exclude=\u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.pyc'\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"16-4-保留最近结果-同时记录错误\"\u003e16.4 保留最近结果,同时记录错误\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20python%20manage.py%20migrate%20%3E%20migrate.log%202%3E%261%0A%24%20tail%20-n%2030%20migrate.log\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003epython manage.py migrate \u0026gt; migrate.log 2\u0026gt;\u0026amp;1\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etail\u003c/span\u003e -n 30 migrate.log\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"16-5-把最近一天的-log-文件归档到目录\"\u003e16.5 把最近一天的 \u003ccode\u003e.log\u003c/code\u003e 文件归档到目录\u003c/h3\u003e\u003cp\u003e先只查看:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20.%2Flogs%20-type%20f%20-name%20'*.log'%20-mtime%20-1%20-print\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ./logs -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -mtime -1 -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eprint\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e确认后再复制:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20mkdir%20-p%20backup%2Frecent%0A%24%20find%20.%2Flogs%20-type%20f%20-name%20'*.log'%20-mtime%20-1%20-exec%20cp%20-t%20backup%2Frecent%20--%20%7B%7D%20%2B\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003emkdir\u003c/span\u003e -p backup/recent\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ./logs -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -mtime -1 -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eexec\u003c/span\u003e \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecp\u003c/span\u003e -t backup/recent -- {} +\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"17-高频面试问答\"\u003e17. 高频面试问答\u003c/h2\u003e\u003ch3 id=\"17-1-绝对路径和相对路径有什么区别\"\u003e17.1 绝对路径和相对路径有什么区别?\u003c/h3\u003e\u003cp\u003e绝对路径从根目录 \u003ccode\u003e/\u003c/code\u003e 开始,不依赖当前目录;相对路径从当前工作目录开始,结果会受 \u003ccode\u003epwd\u003c/code\u003e 影响。\u003c/p\u003e\n\u003ch3 id=\"17-2-和-有什么区别\"\u003e17.2 \u003ccode\u003e\u0026gt;\u003c/code\u003e 和 \u003ccode\u003e\u0026gt;\u0026gt;\u003c/code\u003e 有什么区别?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003e\u0026gt;\u003c/code\u003e 覆盖目标文件,\u003ccode\u003e\u0026gt;\u0026gt;\u003c/code\u003e 追加到文件尾部。两者默认只处理标准输出,错误输出需要使用 \u003ccode\u003e2\u0026gt;\u003c/code\u003e 等写法。\u003c/p\u003e\n\u003ch3 id=\"17-3-管道和重定向有什么区别\"\u003e17.3 管道和重定向有什么区别?\u003c/h3\u003e\u003cp\u003e管道把一个命令的标准输出交给另一个命令的标准输入;重定向改变标准输入、标准输出或标准错误所连接的位置,通常是文件。\u003c/p\u003e\n\u003ch3 id=\"17-4-find-和-grep-的区别\"\u003e17.4 \u003ccode\u003efind\u003c/code\u003e 和 \u003ccode\u003egrep\u003c/code\u003e 的区别?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003efind\u003c/code\u003e 主要按名称、类型、大小、时间等文件属性查找文件;\u003ccode\u003egrep\u003c/code\u003e 主要在文本内容中查找匹配行。两者经常组合使用。\u003c/p\u003e\n\u003ch3 id=\"17-5-which-为什么找不到-cd\"\u003e17.5 \u003ccode\u003ewhich\u003c/code\u003e 为什么找不到 \u003ccode\u003ecd\u003c/code\u003e?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003ecd\u003c/code\u003e 通常是 Shell 内建命令,不是通过 \u003ccode\u003ePATH\u003c/code\u003e 搜索的普通外部程序。使用 \u003ccode\u003etype cd\u003c/code\u003e 能正确识别它。\u003c/p\u003e\n\u003ch3 id=\"17-6-tail-f-与-tail-f-的区别\"\u003e17.6 \u003ccode\u003etail -f\u003c/code\u003e 与 \u003ccode\u003etail -F\u003c/code\u003e 的区别?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003e-f\u003c/code\u003e 持续读取当前文件描述符;\u003ccode\u003e-F\u003c/code\u003e 还会按文件名重试,日志轮转导致原文件被替换时更容易继续追踪。\u003c/p\u003e\n\u003ch3 id=\"17-7-为什么-rm-rf-危险\"\u003e17.7 为什么 \u003ccode\u003erm -rf\u003c/code\u003e 危险?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003e-r\u003c/code\u003e 会递归遍历目录,\u003ccode\u003e-f\u003c/code\u003e 取消确认和多数报错。如果路径、变量或通配符写错,可能快速删除大量数据,而且通常无法从回收站恢复。\u003c/p\u003e\n\u003ch3 id=\"17-8-单引号和双引号有什么区别\"\u003e17.8 单引号和双引号有什么区别?\u003c/h3\u003e\u003cp\u003e单引号基本保留全部字面内容,不展开变量和命令;双引号会展开 \u003ccode\u003e$变量\u003c/code\u003e 和 \u003ccode\u003e$(命令)\u003c/code\u003e,但保留空格并阻止通配展开。\u003c/p\u003e\n\u003ch3 id=\"17-9-21-是什么意思\"\u003e17.9 \u003ccode\u003e2\u0026gt;\u0026amp;1\u003c/code\u003e 是什么意思?\u003c/h3\u003e\u003cp\u003e让文件描述符 2(标准错误)指向文件描述符 1(标准输出)当前指向的位置。它与前后重定向的顺序有关。\u003c/p\u003e\n\u003ch3 id=\"17-10-如何统计出现次数最多的-ip\"\u003e17.10 如何统计出现次数最多的 IP?\u003c/h3\u003e\u003cp\u003e假设访问日志第一列是 IP:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20awk%20'%7Bprint%20%241%7D'%20access.log%20%7C%20sort%20%7C%20uniq%20-c%20%7C%20sort%20-nr%20%7C%20head\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003eawk \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'{print $1}'\u003c/span\u003e access.log | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003esort\u003c/span\u003e | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003euniq\u003c/span\u003e -c | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003esort\u003c/span\u003e -nr | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ehead\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"18-最终自测\"\u003e18. 最终自测\u003c/h2\u003e\u003cp\u003e不看答案完成以下任务:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e在家目录创建 \u003ccode\u003ereview/{src,logs,backup}\u003c/code\u003e。\u003c/li\u003e\n\u003cli\u003e创建三行日志,其中两行包含 \u003ccode\u003eERROR\u003c/code\u003e。\u003c/li\u003e\n\u003cli\u003e显示日志最后两行并持续跟踪。\u003c/li\u003e\n\u003cli\u003e统计 \u003ccode\u003eERROR\u003c/code\u003e 行数。\u003c/li\u003e\n\u003cli\u003e把标准输出和错误同时保存到 \u003ccode\u003erun.log\u003c/code\u003e。\u003c/li\u003e\n\u003cli\u003e查找当前目录下 24 小时内修改的 \u003ccode\u003e.py\u003c/code\u003e 文件。\u003c/li\u003e\n\u003cli\u003e递归搜索项目中出现 \u003ccode\u003eDEBUG=True\u003c/code\u003e 的文件并显示行号。\u003c/li\u003e\n\u003cli\u003e用一条命令把查询结果同时显示并保存。\u003c/li\u003e\n\u003cli\u003e解释 \u003ccode\u003erm -rf \"$target\"\u003c/code\u003e 中为什么变量必须加双引号,以及为什么执行前仍要验证目标。\u003c/li\u003e\n\u003cli\u003e在 Vim 中完成搜索、替换、保存退出。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e一组参考命令:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20mkdir%20-p%20~%2Freview%2F%7Bsrc%2Clogs%2Cbackup%7D%0A%24%20printf%20'INFO%20start%5CnERROR%20db%5CnERROR%20permission%5Cn'%20%3E%20~%2Freview%2Flogs%2Fapp.log%0A%24%20tail%20-n%202%20-f%20~%2Freview%2Flogs%2Fapp.log%0A%24%20grep%20-c%20'ERROR'%20~%2Freview%2Flogs%2Fapp.log%0A%24%20command%20%3E%20~%2Freview%2Frun.log%202%3E%261%0A%24%20find%20.%20-type%20f%20-name%20'*.py'%20-mtime%20-1%0A%24%20grep%20-RniF%20'DEBUG%3DTrue'%20.%0A%24%20grep%20-n%20'ERROR'%20~%2Freview%2Flogs%2Fapp.log%20%7C%20tee%20~%2Freview%2Fbackup%2Ferrors.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003emkdir\u003c/span\u003e -p ~/review/{src,logs,backup}\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eprintf\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'INFO start\\nERROR db\\nERROR permission\\n'\u003c/span\u003e \u0026gt; ~/review/logs/app.log\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etail\u003c/span\u003e -n 2 -f ~/review/logs/app.log\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep -c \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e ~/review/logs/app.log\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; ~/review/run.log 2\u0026gt;\u0026amp;1\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.py'\u003c/span\u003e -mtime -1\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep -RniF \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'DEBUG=True'\u003c/span\u003e .\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep -n \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e ~/review/logs/app.log | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etee\u003c/span\u003e ~/review/backup/errors.txt\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e","cover_image":null,"category_id":null,"author_id":1,"status":"published","view_count":0,"is_pinned":0,"allow_comments":1,"published_at":"2026-07-30T07:13:43.264Z","created_at":"2026-07-30 07:13:43","updated_at":"2026-07-30 07:13:43","asset_dir":"Linux-基础命令复习手册","first_published_at":"2026-07-30T07:13:43.264Z","archived_at":null,"series_id":null,"series_order":0,"pinned_order":0,"course_section":null,"category_name":null,"category_slug":null,"category_description":null,"series_name":null,"series_slug":null,"series_description":null,"series_cover_image":null,"cover_image_sources":null,"category":null,"series":null,"tags":[],"comment_count":0,"series_navigation":{"prev":null,"next":null}},"html":"\u003ch1 id=\"linux-基础命令复习手册\"\u003eLinux 基础命令复习手册\u003c/h1\u003e\u003cblockquote\u003e\n\u003cp\u003e目标:能独立完成文件操作、内容检索、管道组合和日志查看,并能解释命令背后的工作方式。示例统一使用普通用户提示符 \u003ccode\u003e$\u003c/code\u003e;\u003ccode\u003e#\u003c/code\u003e 表示 root,复制命令时不要把提示符一起复制。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"1-高频命令总表\"\u003e1. 高频命令总表\u003c/h2\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e任务\u003c/th\u003e\n\u003cth\u003e首选命令\u003c/th\u003e\n\u003cth\u003e高频选项/写法\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e查看目录\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003els\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e-l\u003c/code\u003e、\u003ccode\u003e-a\u003c/code\u003e、\u003ccode\u003e-h\u003c/code\u003e、\u003ccode\u003e-t\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e切换/确认目录\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecd\u003c/code\u003e、\u003ccode\u003epwd\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecd ..\u003c/code\u003e、\u003ccode\u003ecd -\u003c/code\u003e、\u003ccode\u003ecd ~\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e创建目录/文件\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003emkdir\u003c/code\u003e、\u003ccode\u003etouch\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003emkdir -p\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查看文件\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecat\u003c/code\u003e、\u003ccode\u003eless\u003c/code\u003e、\u003ccode\u003ehead\u003c/code\u003e、\u003ccode\u003etail\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eless -N\u003c/code\u003e、\u003ccode\u003etail -f\u003c/code\u003e、\u003ccode\u003etail -F\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查看文件信息\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003efile\u003c/code\u003e、\u003ccode\u003estat\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003estat 文件\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e复制/移动\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecp\u003c/code\u003e、\u003ccode\u003emv\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecp -a\u003c/code\u003e、\u003ccode\u003ecp -r\u003c/code\u003e、\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e删除\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003erm\u003c/code\u003e、\u003ccode\u003ermdir\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003erm -r\u003c/code\u003e、\u003ccode\u003erm -i\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查找文件\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003efind\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e-name\u003c/code\u003e、\u003ccode\u003e-type\u003c/code\u003e、\u003ccode\u003e-size\u003c/code\u003e、\u003ccode\u003e-mtime\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查找命令\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etype\u003c/code\u003e、\u003ccode\u003ecommand -v\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etype -a\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e过滤内容\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003egrep\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e-n\u003c/code\u003e、\u003ccode\u003e-i\u003c/code\u003e、\u003ccode\u003e-r\u003c/code\u003e、\u003ccode\u003e-E\u003c/code\u003e、\u003ccode\u003e-v\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e统计内容\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ewc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e-l\u003c/code\u003e、\u003ccode\u003e-w\u003c/code\u003e、\u003ccode\u003e-c\u003c/code\u003e、\u003ccode\u003e-m\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e排序去重\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esort\u003c/code\u003e、\u003ccode\u003euniq\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003esort -n\u003c/code\u003e、\u003ccode\u003esort -u\u003c/code\u003e、\u003ccode\u003euniq -c\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e提取列\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecut\u003c/code\u003e、\u003ccode\u003eawk\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecut -d: -f1\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e管道\u003c/td\u003e\n\u003ctd\u003e`\u003c/td\u003e\n\u003ctd\u003e`\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e重定向\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e\u0026gt;\u003c/code\u003e、\u003ccode\u003e\u0026gt;\u0026gt;\u003c/code\u003e、\u003ccode\u003e2\u0026gt;\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e覆盖、追加、重定向错误\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e同时看并保存\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etee\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e`命令\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e编辑文件\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003evim\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ei\u003c/code\u003e、\u003ccode\u003eEsc\u003c/code\u003e、\u003ccode\u003e:wq\u003c/code\u003e、\u003ccode\u003e:q!\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查帮助\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e--help\u003c/code\u003e、\u003ccode\u003eman\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eman 5 passwd\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003ch3 id=\"必须认识的目录\"\u003e必须认识的目录\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e目录\u003c/th\u003e\n\u003cth\u003e主要内容\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e整棵目录树的根\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/home\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e普通用户家目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/root\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eroot 的家目录,不是根目录 \u003ccode\u003e/\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/etc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e系统和服务配置\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/var\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e经常变化的数据,如日志、缓存、队列\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/var/log\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e常见日志目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/usr/bin\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e大量普通命令\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/usr/sbin\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e大量系统管理命令\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/tmp\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e临时文件,可能被系统清理\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/opt\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e可选的第三方软件\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/srv\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e服务对外提供的数据\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/dev\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e设备文件\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/proc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e内核和进程信息的虚拟文件系统\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/sys\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e设备与内核对象信息的虚拟文件系统\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003chr\u003e\n\u003ch2 id=\"2-先准备一套统一练习数据\"\u003e2. 先准备一套统一练习数据\u003c/h2\u003e\u003cp\u003e后面的命令都围绕 \u003ccode\u003e~/linux-lab\u003c/code\u003e 演示:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20mkdir%20-p%20~%2Flinux-lab%2F%7Bapp%2Cdata%2Clogs%2Cbackup%7D%0A%0A%5Bmia%40linux%20~%5D%24%20cat%20%3E%20~%2Flinux-lab%2Fdata%2Fusers.txt%20%3C%3C'EOF'%0A1001%20alice%20backend%20active%0A1002%20bob%20frontend%20active%0A1003%20carol%20backend%20disabled%0A1004%20dave%20ops%20active%0AEOF%0A%0A%5Bmia%40linux%20~%5D%24%20cat%20%3E%20~%2Flinux-lab%2Flogs%2Fapp.log%20%3C%3C'EOF'%0A2026-07-29%2009%3A00%3A01%20INFO%20%20server%20started%20port%3D8000%0A2026-07-29%2009%3A02%3A16%20INFO%20%20GET%20%2Fposts%20status%3D200%0A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A2026-07-29%2009%3A04%3A03%20WARN%20%20slow%20request%20cost%3D1.82s%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload%0AEOF%0A%0A%5Bmia%40linux%20~%5D%24%20printf%20'DEBUG%3Dfalse%5CnPORT%3D8000%5Cn'%20%3E%20~%2Flinux-lab%2Fapp%2Fconfig.env%0A%5Bmia%40linux%20~%5D%24%20touch%20~%2Flinux-lab%2Fapp%2Fmain.py\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ mkdir -p ~/linux-lab/{app,data,logs,backup}\n\n[mia@linux ~]$ cat \u0026gt; ~/linux-lab/data/users.txt \u0026lt;\u0026lt;'EOF'\n1001 alice backend active\n1002 bob frontend active\n1003 carol backend disabled\n1004 dave ops active\nEOF\n\n[mia@linux ~]$ cat \u0026gt; ~/linux-lab/logs/app.log \u0026lt;\u0026lt;'EOF'\n2026-07-29 09:00:01 INFO server started port=8000\n2026-07-29 09:02:16 INFO GET /posts status=200\n2026-07-29 09:03:40 ERROR database timeout request_id=r101\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\nEOF\n\n[mia@linux ~]$ printf 'DEBUG=false\\nPORT=8000\\n' \u0026gt; ~/linux-lab/app/config.env\n[mia@linux ~]$ touch ~/linux-lab/app/main.py\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e查看结构:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20find%20~%2Flinux-lab%20-maxdepth%202%20-printf%20'%25P%5Cn'%20%7C%20sort%0A%0Aapp%0Aapp%2Fconfig.env%0Aapp%2Fmain.py%0Abackup%0Adata%0Adata%2Fusers.txt%0Alogs%0Alogs%2Fapp.log\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ find ~/linux-lab -maxdepth 2 -printf '%P\\n' | sort\n\napp\napp/config.env\napp/main.py\nbackup\ndata\ndata/users.txt\nlogs\nlogs/app.log\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e开头出现的空行代表 \u003ccode\u003e~/linux-lab\u003c/code\u003e 本身;这是 \u003ccode\u003efind\u003c/code\u003e 的正常结果。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"3-linux-目录树与路径\"\u003e3. Linux 目录树与路径\u003c/h2\u003e\u003ch3 id=\"3-1-linux-只有一棵目录树\"\u003e3.1 Linux 只有一棵目录树\u003c/h3\u003e\u003cp\u003eWindows 常见 \u003ccode\u003eC:\\\u003c/code\u003e、\u003ccode\u003eD:\\\u003c/code\u003e 多个盘符;Linux 从唯一的根目录 \u003ccode\u003e/\u003c/code\u003e 开始。其他磁盘和文件系统通常被\u003cstrong\u003e挂载\u003c/strong\u003e到这棵树的某个目录。\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%2F%0A%E2%94%9C%E2%94%80%E2%94%80%20etc%0A%E2%94%9C%E2%94%80%E2%94%80%20home%0A%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20mia%0A%E2%94%9C%E2%94%80%E2%94%80%20usr%0A%E2%94%9C%E2%94%80%E2%94%80%20var%0A%E2%94%94%E2%94%80%E2%94%80%20...\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003e/\n├── etc\n├── home\n│ └── mia\n├── usr\n├── var\n└── ...\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"3-2-绝对路径与相对路径\"\u003e3.2 绝对路径与相对路径\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e路径\u003c/th\u003e\n\u003cth\u003e起点\u003c/th\u003e\n\u003cth\u003e示例\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e绝对路径\u003c/td\u003e\n\u003ctd\u003e根目录 \u003ccode\u003e/\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e/home/mia/linux-lab/logs/app.log\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e相对路径\u003c/td\u003e\n\u003ctd\u003e当前工作目录\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003elogs/app.log\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cd%20~%2Flinux-lab%0A%5Bmia%40linux%20linux-lab%5D%24%20pwd%0A%2Fhome%2Fmia%2Flinux-lab%0A%0A%5Bmia%40linux%20linux-lab%5D%24%20cat%20logs%2Fapp.log%0A2026-07-29%2009%3A00%3A01%20INFO%20%20server%20started%20port%3D8000%0A...%0A%0A%5Bmia%40linux%20linux-lab%5D%24%20cat%20%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A00%3A01%20INFO%20%20server%20started%20port%3D8000%0A...\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cd ~/linux-lab\n[mia@linux linux-lab]$ pwd\n/home/mia/linux-lab\n\n[mia@linux linux-lab]$ cat logs/app.log\n2026-07-29 09:00:01 INFO server started port=8000\n...\n\n[mia@linux linux-lab]$ cat /home/mia/linux-lab/logs/app.log\n2026-07-29 09:00:01 INFO server started port=8000\n...\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"3-3-特殊路径\"\u003e3.3 特殊路径\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e写法\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e.\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e当前目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e..\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e上一级目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e~\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e当前用户家目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e~alice\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e用户 alice 的家目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecd\u003c/code\u003e 中表示上一次所在目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20linux-lab%5D%24%20cd%20logs%0A%5Bmia%40linux%20logs%5D%24%20cd%20..%0A%5Bmia%40linux%20linux-lab%5D%24%20cd%20-%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%0A%5Bmia%40linux%20logs%5D%24%20cd%0A%5Bmia%40linux%20~%5D%24\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux linux-lab]$ cd logs\n[mia@linux logs]$ cd ..\n[mia@linux linux-lab]$ cd -\n/home/mia/linux-lab/logs\n[mia@linux logs]$ cd\n[mia@linux ~]$\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003ecd\u003c/code\u003e 不带参数等价于回到当前用户的家目录。\u003c/p\u003e\n\u003ch3 id=\"3-4-文件名-隐藏文件与大小写\"\u003e3.4 文件名、隐藏文件与大小写\u003c/h3\u003e\u003cul\u003e\n\u003cli\u003e以 \u003ccode\u003e.\u003c/code\u003e 开头的名称默认隐藏,例如 \u003ccode\u003e.bashrc\u003c/code\u003e。\u003c/li\u003e\n\u003cli\u003eLinux 文件名通常区分大小写:\u003ccode\u003eApp.py\u003c/code\u003e 与 \u003ccode\u003eapp.py\u003c/code\u003e 是两个名称。\u003c/li\u003e\n\u003cli\u003e扩展名不决定文件本质,\u003ccode\u003efile\u003c/code\u003e 会根据内容判断类型。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20ls%0Alinux-lab%0A%0A%5Bmia%40linux%20~%5D%24%20ls%20-a%0A.%20%20..%20%20.bashrc%20%20.ssh%20%20linux-lab%0A%0A%5Bmia%40linux%20~%5D%24%20file%20~%2Flinux-lab%2Flogs%2Fapp.log%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%3A%20ASCII%20text\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ ls\nlinux-lab\n\n[mia@linux ~]$ ls -a\n. .. .bashrc .ssh linux-lab\n\n[mia@linux ~]$ file ~/linux-lab/logs/app.log\n/home/mia/linux-lab/logs/app.log: ASCII text\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"4-命令的基本结构\"\u003e4. 命令的基本结构\u003c/h2\u003e\u003cp\u003e常见形式:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"command%20%5Boptions%5D%20%5Barguments%5D\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003ecommand [options] [arguments]\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20ls%20-lah%20~%2Flinux-lab\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ ls -lah ~/linux-lab\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\u003ccode\u003els\u003c/code\u003e:命令;\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e-l\u003c/code\u003e、\u003ccode\u003e-a\u003c/code\u003e、\u003ccode\u003e-h\u003c/code\u003e:选项;\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e~/linux-lab\u003c/code\u003e:参数。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e短选项常可合并,下面三种通常等价:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20ls%20-l%20-a%20-h%0A%24%20ls%20-lah%0A%24%20ls%20-hal\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003els\u003c/span\u003e -l -a -h\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003els\u003c/span\u003e -lah\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003els\u003c/span\u003e -hal\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e长选项通常以两个连字符开头:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20ls%20--all%20--human-readable\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003els\u003c/span\u003e --all --human-readable\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"4-1-如何查帮助\"\u003e4.1 如何查帮助\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20ls%20--help%20%7C%20head%0AUsage%3A%20ls%20%5BOPTION%5D...%20%5BFILE%5D...%0AList%20information%20about%20the%20FILEs%20...%0A%0A%5Bmia%40linux%20~%5D%24%20man%20ls%0ALS(1)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20User%20Commands%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20LS(1)\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ ls --help | head\nUsage: ls [OPTION]... [FILE]...\nList information about the FILEs ...\n\n[mia@linux ~]$ man ls\nLS(1) User Commands LS(1)\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e在 \u003ccode\u003eman\u003c/code\u003e 中:\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e按键\u003c/th\u003e\n\u003cth\u003e作用\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eSpace\u003c/code\u003e / \u003ccode\u003ePageDown\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下一页\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eb\u003c/code\u003e / \u003ccode\u003ePageUp\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e上一页\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/word\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e向下搜索\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003en\u003c/code\u003e / \u003ccode\u003eN\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下一个/上一个匹配\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eq\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e退出\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e手册分章节,例如:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20man%201%20passwd%20%20%20%20%23%20passwd%20%E5%91%BD%E4%BB%A4%0A%24%20man%205%20passwd%20%20%20%20%23%20%2Fetc%2Fpasswd%20%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003eman 1 passwd \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# passwd 命令\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003eman 5 passwd \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# /etc/passwd 文件格式\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"5-查看目录-ls\"\u003e5. 查看目录:\u003ccode\u003els\u003c/code\u003e\u003c/h2\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20ls%20-lah%20~%2Flinux-lab%0Atotal%200%0Adrwxr-xr-x%206%20mia%20mia%20%2059%20Jul%2029%2009%3A00%20.%0Adrwx------%208%20mia%20mia%20190%20Jul%2029%2008%3A50%20..%0Adrwxr-xr-x%202%20mia%20mia%20%2039%20Jul%2029%2009%3A00%20app%0Adrwxr-xr-x%202%20mia%20mia%20%20%206%20Jul%2029%2009%3A00%20backup%0Adrwxr-xr-x%202%20mia%20mia%20%2023%20Jul%2029%2009%3A00%20data%0Adrwxr-xr-x%202%20mia%20mia%20%2021%20Jul%2029%2009%3A00%20logs\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ ls -lah ~/linux-lab\ntotal 0\ndrwxr-xr-x 6 mia mia 59 Jul 29 09:00 .\ndrwx------ 8 mia mia 190 Jul 29 08:50 ..\ndrwxr-xr-x 2 mia mia 39 Jul 29 09:00 app\ndrwxr-xr-x 2 mia mia 6 Jul 29 09:00 backup\ndrwxr-xr-x 2 mia mia 23 Jul 29 09:00 data\ndrwxr-xr-x 2 mia mia 21 Jul 29 09:00 logs\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e常用选项:\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e选项\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-l\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e长格式\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-a\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e包括隐藏项\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-h\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e配合 \u003ccode\u003e-l\u003c/code\u003e,用 KiB、MiB、GiB 等易读单位\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-t\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e按修改时间排序\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-r\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e反向排序\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-d\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e查看目录本身,不列出目录内容\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示 inode 号\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e\u003ccode\u003els -l\u003c/code\u003e 一行大致包含:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"-rw-r--r--%201%20mia%20developers%20245%20Jul%2029%2009%3A05%20app.log%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%82%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%20%E5%90%8D%E7%A7%B0%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%82%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%E2%94%94%E2%94%80%20%E4%BF%AE%E6%94%B9%E6%97%B6%E9%97%B4%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%82%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%20%E5%A4%A7%E5%B0%8F%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%82%20%20%20%E2%94%94%E2%94%80%20%E6%89%80%E5%B1%9E%E7%BB%84%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%E2%94%94%E2%94%80%20%E6%89%80%E5%B1%9E%E7%94%A8%E6%88%B7%0A%E2%94%82%20%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%20%E7%A1%AC%E9%93%BE%E6%8E%A5%E6%95%B0%0A%E2%94%94%E2%94%80%20%E6%96%87%E4%BB%B6%E7%B1%BB%E5%9E%8B%E4%B8%8E%E6%9D%83%E9%99%90\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003e-rw-r--r-- 1 mia developers 245 Jul 29 09:05 app.log\n│ │ │ │ │ │ └─ 名称\n│ │ │ │ │ └─ 修改时间\n│ │ │ │ └─ 大小\n│ │ │ └─ 所属组\n│ │ └─ 所属用户\n│ └─ 硬链接数\n└─ 文件类型与权限\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e不要用解析 \u003ccode\u003els\u003c/code\u003e 输出的方式编写严肃脚本;文件名可能包含空格、换行等特殊字符。脚本中更适合使用 \u003ccode\u003efind -print0\u003c/code\u003e 等安全接口。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"6-创建目录和文件\"\u003e6. 创建目录和文件\u003c/h2\u003e\u003ch3 id=\"6-1-mkdir\"\u003e6.1 \u003ccode\u003emkdir\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20mkdir%20~%2Fdemo%0A%0A%5Bmia%40linux%20~%5D%24%20mkdir%20~%2Fa%2Fb%2Fc%0Amkdir%3A%20cannot%20create%20directory%20%E2%80%98%2Fhome%2Fmia%2Fa%2Fb%2Fc%E2%80%99%3A%20No%20such%20file%20or%20directory%0A%0A%5Bmia%40linux%20~%5D%24%20mkdir%20-p%20~%2Fa%2Fb%2Fc%0A%5Bmia%40linux%20~%5D%24%20ls%20-d%20~%2Fa%2Fb%2Fc%0A%2Fhome%2Fmia%2Fa%2Fb%2Fc\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ mkdir ~/demo\n\n[mia@linux ~]$ mkdir ~/a/b/c\nmkdir: cannot create directory ‘/home/mia/a/b/c’: No such file or directory\n\n[mia@linux ~]$ mkdir -p ~/a/b/c\n[mia@linux ~]$ ls -d ~/a/b/c\n/home/mia/a/b/c\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e-p\u003c/code\u003e:父目录不存在时一起创建;目录已存在时不报错。\u003c/li\u003e\n\u003cli\u003e一次创建多个同级目录可用花括号展开:\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20mkdir%20-p%20project%2F%7Bsrc%2Ctests%2Cdocs%2Clogs%7D\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003emkdir\u003c/span\u003e -p project/{src,tests,docs,logs}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e花括号展开由 Shell 完成,不是 \u003ccode\u003emkdir\u003c/code\u003e 独有功能。\u003c/p\u003e\n\u003ch3 id=\"6-2-touch\"\u003e6.2 \u003ccode\u003etouch\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20touch%20notes.txt%0A%5Bmia%40linux%20~%5D%24%20ls%20-l%20notes.txt%0A-rw-r--r--%201%20mia%20mia%200%20Jul%2029%2010%3A12%20notes.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ touch notes.txt\n[mia@linux ~]$ ls -l notes.txt\n-rw-r--r-- 1 mia mia 0 Jul 29 10:12 notes.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003etouch\u003c/code\u003e 的准确作用是更新访问/修改时间;文件不存在时才会顺便创建空文件。\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20stat%20-c%20'%25y%20%25n'%20notes.txt%0A2026-07-29%2010%3A12%3A00.000000000%20-0700%20notes.txt%0A%0A%5Bmia%40linux%20~%5D%24%20touch%20notes.txt%0A%5Bmia%40linux%20~%5D%24%20stat%20-c%20'%25y%20%25n'%20notes.txt%0A2026-07-29%2010%3A15%3A34.000000000%20-0700%20notes.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ stat -c '%y %n' notes.txt\n2026-07-29 10:12:00.000000000 -0700 notes.txt\n\n[mia@linux ~]$ touch notes.txt\n[mia@linux ~]$ stat -c '%y %n' notes.txt\n2026-07-29 10:15:34.000000000 -0700 notes.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"6-3-file-与-stat\"\u003e6.3 \u003ccode\u003efile\u003c/code\u003e 与 \u003ccode\u003estat\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20file%20~%2Flinux-lab%2Fapp%2Fmain.py%0A%2Fhome%2Fmia%2Flinux-lab%2Fapp%2Fmain.py%3A%20empty%0A%0A%5Bmia%40linux%20~%5D%24%20stat%20~%2Flinux-lab%2Flogs%2Fapp.log%0A%20%20File%3A%20%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%0A%20%20Size%3A%20281%20%20%20%20%20%20%20%20Blocks%3A%208%20%20%20%20%20%20%20%20%20%20IO%20Block%3A%204096%20regular%20file%0AAccess%3A%20(0644%2F-rw-r--r--)%20%20Uid%3A%20(1000%2Fmia)%20%20%20Gid%3A%20(1000%2Fmia)\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ file ~/linux-lab/app/main.py\n/home/mia/linux-lab/app/main.py: empty\n\n[mia@linux ~]$ stat ~/linux-lab/logs/app.log\n File: /home/mia/linux-lab/logs/app.log\n Size: 281 Blocks: 8 IO Block: 4096 regular file\nAccess: (0644/-rw-r--r--) Uid: (1000/mia) Gid: (1000/mia)\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"7-查看文件内容\"\u003e7. 查看文件内容\u003c/h2\u003e\u003ch3 id=\"7-1-怎么选命令\"\u003e7.1 怎么选命令\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e场景\u003c/th\u003e\n\u003cth\u003e命令\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e小文件一次全部输出\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecat file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e大文件分页查看\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eless file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查看开头\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ehead file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e查看结尾\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etail file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e持续跟踪日志\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003etail -f file\u003c/code\u003e 或 \u003ccode\u003etail -F file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e带行号查看\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003enl -ba file\u003c/code\u003e 或 \u003ccode\u003eless -N file\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003ch3 id=\"7-2-cat\"\u003e7.2 \u003ccode\u003ecat\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cat%20~%2Flinux-lab%2Fapp%2Fconfig.env%0ADEBUG%3Dfalse%0APORT%3D8000%0A%0A%5Bmia%40linux%20~%5D%24%20cat%20-n%20~%2Flinux-lab%2Fapp%2Fconfig.env%0A%20%20%20%20%201%20%20DEBUG%3Dfalse%0A%20%20%20%20%202%20%20PORT%3D8000\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cat ~/linux-lab/app/config.env\nDEBUG=false\nPORT=8000\n\n[mia@linux ~]$ cat -n ~/linux-lab/app/config.env\n 1 DEBUG=false\n 2 PORT=8000\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003ecat\u003c/code\u003e 还能连接多个文件:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20cat%20part1.txt%20part2.txt%20%3E%20all.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecat\u003c/span\u003e part1.txt part2.txt \u0026gt; all.txt\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"7-3-less\"\u003e7.3 \u003ccode\u003eless\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20less%20-N%20%2Fetc%2Fservices\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ less -N /etc/services\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e常用按键与 \u003ccode\u003eman\u003c/code\u003e 类似:\u003ccode\u003eSpace\u003c/code\u003e 翻页、\u003ccode\u003e/关键词\u003c/code\u003e 搜索、\u003ccode\u003en\u003c/code\u003e 下一个、\u003ccode\u003eq\u003c/code\u003e 退出。\u003ccode\u003eless\u003c/code\u003e 通常比 \u003ccode\u003emore\u003c/code\u003e 功能更完整。\u003c/p\u003e\n\u003ch3 id=\"7-4-head-与-tail\"\u003e7.4 \u003ccode\u003ehead\u003c/code\u003e 与 \u003ccode\u003etail\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20head%20-n%202%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A00%3A01%20INFO%20%20server%20started%20port%3D8000%0A2026-07-29%2009%3A02%3A16%20INFO%20%20GET%20%2Fposts%20status%3D200%0A%0A%5Bmia%40linux%20~%5D%24%20tail%20-n%202%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A04%3A03%20WARN%20%20slow%20request%20cost%3D1.82s%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ head -n 2 ~/linux-lab/logs/app.log\n2026-07-29 09:00:01 INFO server started port=8000\n2026-07-29 09:02:16 INFO GET /posts status=200\n\n[mia@linux ~]$ tail -n 2 ~/linux-lab/logs/app.log\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e持续追踪:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20tail%20-f%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ tail -f ~/linux-lab/logs/app.log\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e另一个终端追加内容:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20echo%20'2026-07-29%2009%3A08%3A11%20INFO%20%20worker%20ready'%20%3E%3E%20~%2Flinux-lab%2Flogs%2Fapp.log\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ echo '2026-07-29 09:08:11 INFO worker ready' \u0026gt;\u0026gt; ~/linux-lab/logs/app.log\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003etail -F\u003c/code\u003e 在日志轮转、文件被重新创建后会尝试继续跟踪,比 \u003ccode\u003e-f\u003c/code\u003e 更适合长期盯日志。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"8-复制-移动与删除\"\u003e8. 复制、移动与删除\u003c/h2\u003e\u003ch3 id=\"8-1-cp\"\u003e8.1 \u003ccode\u003ecp\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cp%20~%2Flinux-lab%2Fapp%2Fconfig.env%20~%2Flinux-lab%2Fbackup%2Fconfig.env.bak%0A%0A%5Bmia%40linux%20~%5D%24%20cp%20-r%20~%2Flinux-lab%2Fapp%20~%2Flinux-lab%2Fbackup%2F%0A%0A%5Bmia%40linux%20~%5D%24%20cp%20-a%20~%2Flinux-lab%2Fapp%20~%2Flinux-lab%2Fbackup%2Fapp-full\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cp ~/linux-lab/app/config.env ~/linux-lab/backup/config.env.bak\n\n[mia@linux ~]$ cp -r ~/linux-lab/app ~/linux-lab/backup/\n\n[mia@linux ~]$ cp -a ~/linux-lab/app ~/linux-lab/backup/app-full\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e选项\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-r\u003c/code\u003e / \u003ccode\u003e-R\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e递归复制目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-a\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e归档复制,尽量保留权限、时间、链接等属性\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e覆盖前询问\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-n\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e不覆盖已有目标\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-v\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示操作过程\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e复制多个源时,最后一个参数必须是已存在的目录:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20cp%20a.txt%20b.txt%20backup%2F\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecp\u003c/span\u003e a.txt b.txt backup/\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"8-2-mv\"\u003e8.2 \u003ccode\u003emv\u003c/code\u003e\u003c/h3\u003e\u003cp\u003e\u003ccode\u003emv\u003c/code\u003e 同时承担移动和重命名:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20mv%20old.txt%20new.txt%0A%0A%5Bmia%40linux%20~%5D%24%20mv%20new.txt%20~%2Flinux-lab%2Fbackup%2F\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ mv old.txt new.txt\n\n[mia@linux ~]$ mv new.txt ~/linux-lab/backup/\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e目标不存在:通常表示重命名。\u003c/li\u003e\n\u003cli\u003e目标是已存在的目录:移动到该目录内。\u003c/li\u003e\n\u003cli\u003e同一文件系统内移动通常只修改目录项,很快;跨文件系统时可能变成复制后删除。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"8-3-rm\"\u003e8.3 \u003ccode\u003erm\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20rm%20old.log%0A%5Bmia%40linux%20~%5D%24%20rm%20-r%20old-directory%0A%5Bmia%40linux%20~%5D%24%20rm%20-i%20important.conf%0Arm%3A%20remove%20regular%20file%20'important.conf'%3F%20n\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ rm old.log\n[mia@linux ~]$ rm -r old-directory\n[mia@linux ~]$ rm -i important.conf\nrm: remove regular file 'important.conf'? n\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e选项\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-r\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e递归删除目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-f\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e强制,不询问并忽略不存在的文件\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e每次删除前询问\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-I\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e大量删除或递归删除前询问一次\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e\u003ccode\u003erm\u003c/code\u003e 默认是否询问与别名和选项有关,不是简单按“普通用户/root”区分。\u003c/p\u003e\n\u003ch3 id=\"8-4-删除前的安全习惯\"\u003e8.4 删除前的安全习惯\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%23%201.%20%E5%85%88%E6%89%93%E5%8D%B0%E7%9B%AE%E6%A0%87%0A%5Bmia%40linux%20logs%5D%24%20printf%20'%3C%25s%3E%5Cn'%20*.log%0A%3Capp.log%3E%0A%3Cold.log%3E%0A%0A%23%202.%20%E5%86%8D%E5%88%A0%E9%99%A4%EF%BC%8C%E5%B9%B6%E8%AE%A9%E5%8D%B1%E9%99%A9%E6%93%8D%E4%BD%9C%E8%AF%A2%E9%97%AE%E4%B8%80%E6%AC%A1%0A%5Bmia%40linux%20logs%5D%24%20rm%20-I%20--%20*.log%0Arm%3A%20remove%202%20arguments%3F%20n\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e# \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e1. 先打印目标\u003c/span\u003e\n[mia@linux logs]$ printf '\u0026lt;%s\u0026gt;\\n' *.log\n\u0026lt;app.log\u0026gt;\n\u0026lt;old.log\u0026gt;\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e\n# \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e2. 再删除,并让危险操作询问一次\u003c/span\u003e\n[mia@linux logs]$ rm -I -- *.log\nrm: remove 2 arguments? n\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e先用 \u003ccode\u003epwd\u003c/code\u003e、\u003ccode\u003els\u003c/code\u003e 或 \u003ccode\u003eprintf\u003c/code\u003e 确认当前目录和通配结果。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e--\u003c/code\u003e 表示选项结束,可安全处理名称以 \u003ccode\u003e-\u003c/code\u003e 开头的文件。\u003c/li\u003e\n\u003cli\u003e不要执行 \u003ccode\u003erm -rf /\u003c/code\u003e、\u003ccode\u003erm -rf /*\u003c/code\u003e 或目标变量未经检查的递归删除。\u003c/li\u003e\n\u003cli\u003e命令行 \u003ccode\u003erm\u003c/code\u003e 通常不经过回收站。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e删除空目录可用:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20rmdir%20empty-directory\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ermdir\u003c/span\u003e empty-directory\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"9-通配符-引号与命令替换\"\u003e9. 通配符、引号与命令替换\u003c/h2\u003e\u003ch3 id=\"9-1-通配符\"\u003e9.1 通配符\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e写法\u003c/th\u003e\n\u003cth\u003e匹配\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e*\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e任意长度字符,通常不跨 \u003ccode\u003e/\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e任意一个字符\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e[abc]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ea\u003c/code\u003e、\u003ccode\u003eb\u003c/code\u003e、\u003ccode\u003ec\u003c/code\u003e 中任一个\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e[0-9]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e任一个数字\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e[!0-9]\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e任一个非数字字符\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20logs%5D%24%20printf%20'%25s%5Cn'%20*.log%0Aapp.log%0Aold.log%0A%0A%5Bmia%40linux%20data%5D%24%20printf%20'%25s%5Cn'%20user%3F.txt%0Auser1.txt%0Auser2.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux logs]$ printf '%s\\n' *.log\napp.log\nold.log\n\n[mia@linux data]$ printf '%s\\n' user?.txt\nuser1.txt\nuser2.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e通配符一般先由 Shell 展开,再把结果交给命令。\u003c/p\u003e\n\u003ch3 id=\"9-2-单引号-双引号与不加引号\"\u003e9.2 单引号、双引号与不加引号\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20name%3D'Linux'%0A%0A%5Bmia%40linux%20~%5D%24%20echo%20'%24name'%0A%24name%0A%0A%5Bmia%40linux%20~%5D%24%20echo%20%22%24name%22%0ALinux%0A%0A%5Bmia%40linux%20~%5D%24%20echo%20*.txt%0Anotes.txt%20report.txt%0A%0A%5Bmia%40linux%20~%5D%24%20echo%20%22*.txt%22%0A*.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ name='Linux'\n\n[mia@linux ~]$ echo '$name'\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$\u003c/span\u003e\u003cspan class=\"language-bash\"\u003ename\u003c/span\u003e\n\n[mia@linux ~]$ echo \"$name\"\nLinux\n\n[mia@linux ~]$ echo *.txt\nnotes.txt report.txt\n\n[mia@linux ~]$ echo \"*.txt\"\n*.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e写法\u003c/th\u003e\n\u003cth align=\"right\"\u003e变量展开\u003c/th\u003e\n\u003cth align=\"right\"\u003e命令替换\u003c/th\u003e\n\u003cth align=\"right\"\u003e通配展开\u003c/th\u003e\n\u003cth align=\"right\"\u003e保留空格\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e不加引号\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e\"双引号\"\u003c/code\u003e\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e'单引号'\u003c/code\u003e\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003ctd align=\"right\"\u003e否\u003c/td\u003e\n\u003ctd align=\"right\"\u003e是\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cp\u003e变量引用通常写成 \u003ccode\u003e\"$var\"\u003c/code\u003e,避免空格和通配符造成意外拆分。\u003c/p\u003e\n\u003ch3 id=\"9-3-命令替换\"\u003e9.3 命令替换\u003c/h3\u003e\u003cp\u003e推荐使用 \u003ccode\u003e$(...)\u003c/code\u003e,可读性和嵌套性优于旧式反引号:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20echo%20%22%E5%BD%93%E5%89%8D%E7%9B%AE%E5%BD%95%EF%BC%9A%24(pwd)%22%0A%E5%BD%93%E5%89%8D%E7%9B%AE%E5%BD%95%EF%BC%9A%2Fhome%2Fmia%0A%0A%5Bmia%40linux%20~%5D%24%20today%3D%24(date%20%2B%25F)%0A%5Bmia%40linux%20~%5D%24%20echo%20%22%24today%22%0A2026-07-29\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ echo \"当前目录:$(pwd)\"\n当前目录:/home/mia\n\n[mia@linux ~]$ today=$(date +%F)\n[mia@linux ~]$ echo \"$today\"\n2026-07-29\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"10-查找命令与文件\"\u003e10. 查找命令与文件\u003c/h2\u003e\u003ch3 id=\"10-1-type-command-v-which\"\u003e10.1 \u003ccode\u003etype\u003c/code\u003e、\u003ccode\u003ecommand -v\u003c/code\u003e、\u003ccode\u003ewhich\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20type%20cd%0Acd%20is%20a%20shell%20builtin%0A%0A%5Bmia%40linux%20~%5D%24%20type%20-a%20python%0Apython%20is%20%2Fhome%2Fmia%2Fvenv%2Fbin%2Fpython%0Apython%20is%20%2Fusr%2Fbin%2Fpython%0A%0A%5Bmia%40linux%20~%5D%24%20command%20-v%20grep%0A%2Fusr%2Fbin%2Fgrep\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ type cd\ncd is a shell builtin\n\n[mia@linux ~]$ type -a python\npython is /home/mia/venv/bin/python\npython is /usr/bin/python\n\n[mia@linux ~]$ command -v grep\n/usr/bin/grep\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\u003ccode\u003etype\u003c/code\u003e 能识别别名、函数、Shell 内建和外部命令。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecommand -v\u003c/code\u003e 适合脚本判断命令是否存在。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ewhich\u003c/code\u003e 主要搜索 \u003ccode\u003ePATH\u003c/code\u003e 中的可执行文件,对别名和内建命令不一定可靠。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"10-2-find-基本结构\"\u003e10.2 \u003ccode\u003efind\u003c/code\u003e 基本结构\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"find%20%E6%90%9C%E7%B4%A2%E8%B5%B7%E7%82%B9%20%E6%9D%A1%E4%BB%B6%20%E5%8A%A8%E4%BD%9C\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003efind 搜索起点 条件 动作\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e按名称:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20find%20~%2Flinux-lab%20-name%20'app.log'%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%0A%0A%5Bmia%40linux%20~%5D%24%20find%20~%2Flinux-lab%20-iname%20'*.ENV'%0A%2Fhome%2Fmia%2Flinux-lab%2Fapp%2Fconfig.env\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ find ~/linux-lab -name 'app.log'\n/home/mia/linux-lab/logs/app.log\n\n[mia@linux ~]$ find ~/linux-lab -iname '*.ENV'\n/home/mia/linux-lab/app/config.env\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e通配模式要加引号,避免被当前 Shell 提前展开。\u003c/p\u003e\n\u003cp\u003e按类型:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20~%2Flinux-lab%20-type%20f%20%20%20%20%20%23%20%E6%99%AE%E9%80%9A%E6%96%87%E4%BB%B6%0A%24%20find%20~%2Flinux-lab%20-type%20d%20%20%20%20%20%23%20%E7%9B%AE%E5%BD%95%0A%24%20find%20~%2Flinux-lab%20-type%20l%20%20%20%20%20%23%20%E7%AC%A6%E5%8F%B7%E9%93%BE%E6%8E%A5\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ~/linux-lab -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 普通文件\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ~/linux-lab -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e d \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 目录\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ~/linux-lab -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e l \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 符号链接\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e按大小:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20%2Fvar%2Flog%20-type%20f%20-size%20%2B100M%0A%24%20find%20.%20-type%20f%20-size%20-10k\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind /var/log -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -size +100M\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -size -10k\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e按修改时间:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20.%20-type%20f%20-mtime%20-1%20%20%20%20%20%23%20%E7%BA%A6%2024%20%E5%B0%8F%E6%97%B6%E5%86%85%E4%BF%AE%E6%94%B9%0A%24%20find%20.%20-type%20f%20-mtime%20%2B30%20%20%20%20%23%20%E8%B6%85%E8%BF%87%E7%BA%A6%2030%20%E5%A4%A9%0A%24%20find%20.%20-type%20f%20-mmin%20-10%20%20%20%20%20%23%20%E7%BA%A6%2010%20%E5%88%86%E9%92%9F%E5%86%85%E4%BF%AE%E6%94%B9\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -mtime -1 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 约 24 小时内修改\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -mtime +30 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 超过约 30 天\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -mmin -10 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 约 10 分钟内修改\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e组合条件:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20.%20-type%20f%20%5C(%20-name%20'*.log'%20-o%20-name%20'*.txt'%20%5C)%0A%24%20find%20.%20-type%20f%20-name%20'*.log'%20!%20-name%20'debug.log'\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f \\( -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -o -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.txt'\u003c/span\u003e \\)\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e ! -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'debug.log'\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e对结果执行命令:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20find%20~%2Flinux-lab%2Flogs%20-type%20f%20-name%20'*.log'%20%5C%0A%3E%20-exec%20grep%20-Hn%20'ERROR'%20%7B%7D%20%2B%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%3A3%3A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A%2Fhome%2Fmia%2Flinux-lab%2Flogs%2Fapp.log%3A5%3A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ find ~/linux-lab/logs -type f -name '*.log' \\\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e\u0026gt; \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e-\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eexec\u003c/span\u003e grep -Hn \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e {} +\u003c/span\u003e\n/home/mia/linux-lab/logs/app.log:3:2026-07-29 09:03:40 ERROR database timeout request_id=r101\n/home/mia/linux-lab/logs/app.log:5:2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003e{} +\u003c/code\u003e 会把多个结果成批传给命令,通常比每个文件执行一次的 \u003ccode\u003e{} \\;\u003c/code\u003e 更高效。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"11-文本过滤与统计\"\u003e11. 文本过滤与统计\u003c/h2\u003e\u003ch3 id=\"11-1-grep\"\u003e11.1 \u003ccode\u003egrep\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20-n%20'ERROR'%20~%2Flinux-lab%2Flogs%2Fapp.log%0A3%3A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A5%3A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep -n 'ERROR' ~/linux-lab/logs/app.log\n3:2026-07-29 09:03:40 ERROR database timeout request_id=r101\n5:2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e常用选项:\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e选项\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-n\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示行号\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-i\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e忽略大小写\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-v\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e反选,不含匹配内容\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-r\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e递归搜索目录\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-l\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e只显示匹配到的文件名\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-c\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示每个文件的匹配行数\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-E\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e使用扩展正则表达式\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-F\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e把模式当普通字符串,不解释正则符号\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-A 2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示匹配行及后 2 行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-B 2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示匹配行及前 2 行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e-C 2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示匹配行前后各 2 行\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20-E%20'ERROR%7CWARN'%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A2026-07-29%2009%3A04%3A03%20WARN%20%20slow%20request%20cost%3D1.82s%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload%0A%0A%5Bmia%40linux%20~%5D%24%20grep%20-rln%20'DEBUG%3Dfalse'%20~%2Flinux-lab%0A%2Fhome%2Fmia%2Flinux-lab%2Fapp%2Fconfig.env\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep -E 'ERROR|WARN' ~/linux-lab/logs/app.log\n2026-07-29 09:03:40 ERROR database timeout request_id=r101\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\n\n[mia@linux ~]$ grep -rln 'DEBUG=false' ~/linux-lab\n/home/mia/linux-lab/app/config.env\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"11-2-wc\"\u003e11.2 \u003ccode\u003ewc\u003c/code\u003e\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20wc%20~%2Flinux-lab%2Fdata%2Fusers.txt%0A%20%204%20%2016%20105%20%2Fhome%2Fmia%2Flinux-lab%2Fdata%2Fusers.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ wc ~/linux-lab/data/users.txt\n 4 16 105 /home/mia/linux-lab/data/users.txt\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e默认依次显示行数、单词数、字节数。\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20wc%20-l%20file%20%20%20%20%20%20%20%23%20%E8%A1%8C%E6%95%B0%0A%24%20wc%20-w%20file%20%20%20%20%20%20%20%23%20%E5%8D%95%E8%AF%8D%E6%95%B0%0A%24%20wc%20-c%20file%20%20%20%20%20%20%20%23%20%E5%AD%97%E8%8A%82%E6%95%B0%0A%24%20wc%20-m%20file%20%20%20%20%20%20%20%23%20%E5%AD%97%E7%AC%A6%E6%95%B0\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -l file \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 行数\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -w file \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 单词数\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -c file \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 字节数\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -m file \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 字符数\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003eUTF-8 中文字符通常占多个字节,因此 \u003ccode\u003e-c\u003c/code\u003e 与 \u003ccode\u003e-m\u003c/code\u003e 可能不同。\u003c/p\u003e\n\u003ch3 id=\"11-3-sort-uniq-cut\"\u003e11.3 \u003ccode\u003esort\u003c/code\u003e、\u003ccode\u003euniq\u003c/code\u003e、\u003ccode\u003ecut\u003c/code\u003e\u003c/h3\u003e\u003cp\u003e统计每种状态的人数:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20awk%20'%7Bprint%20%244%7D'%20~%2Flinux-lab%2Fdata%2Fusers.txt%20%7C%20sort%20%7C%20uniq%20-c%0A%20%20%20%20%20%203%20active%0A%20%20%20%20%20%201%20disabled\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ awk '{print $4}' ~/linux-lab/data/users.txt | sort | uniq -c\n 3 active\n 1 disabled\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003euniq\u003c/code\u003e 只合并\u003cstrong\u003e相邻\u003c/strong\u003e重复行,所以一般先 \u003ccode\u003esort\u003c/code\u003e。\u003c/p\u003e\n\u003cp\u003e从 \u003ccode\u003e/etc/passwd\u003c/code\u003e 提取用户名和登录 Shell:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cut%20-d%3A%20-f1%2C7%20%2Fetc%2Fpasswd%20%7C%20head%0Aroot%3A%2Fbin%2Fbash%0Abin%3A%2Fsbin%2Fnologin%0Adaemon%3A%2Fsbin%2Fnologin%0A...\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cut -d: -f1,7 /etc/passwd | head\nroot:/bin/bash\nbin:/sbin/nologin\ndaemon:/sbin/nologin\n...\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"12-管道与重定向\"\u003e12. 管道与重定向\u003c/h2\u003e\u003ch3 id=\"12-1-三个标准流\"\u003e12.1 三个标准流\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth align=\"right\"\u003e编号\u003c/th\u003e\n\u003cth\u003e名称\u003c/th\u003e\n\u003cth\u003e默认位置\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd align=\"right\"\u003e\u003ccode\u003e0\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e标准输入 stdin\u003c/td\u003e\n\u003ctd\u003e键盘\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd align=\"right\"\u003e\u003ccode\u003e1\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e标准输出 stdout\u003c/td\u003e\n\u003ctd\u003e终端\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd align=\"right\"\u003e\u003ccode\u003e2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e标准错误 stderr\u003c/td\u003e\n\u003ctd\u003e终端\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003ch3 id=\"12-2-管道\"\u003e12.2 管道 \u003ccode\u003e|\u003c/code\u003e\u003c/h3\u003e\u003cp\u003e管道把左侧命令的\u003cstrong\u003e标准输出\u003c/strong\u003e交给右侧命令的\u003cstrong\u003e标准输入\u003c/strong\u003e:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20'ERROR'%20~%2Flinux-lab%2Flogs%2Fapp.log%20%7C%20wc%20-l%0A2%0A%0A%5Bmia%40linux%20~%5D%24%20ps%20-ef%20%7C%20grep%20'%5Bg%5Dunicorn'%0Amia%20%20%20%20%20%20%203184%20%20%20%20%20%20%201%20%200%2009%3A00%20%3F%20%2000%3A00%3A01%20gunicorn%3A%20master%20%5Bconfig.wsgi%5D\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep 'ERROR' ~/linux-lab/logs/app.log | wc -l\n2\n\n[mia@linux ~]$ ps -ef | grep '[g]unicorn'\nmia 3184 1 0 09:00 ? 00:00:01 gunicorn: master [config.wsgi]\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003egrep '[g]unicorn'\u003c/code\u003e 可以避免把当前 \u003ccode\u003egrep gunicorn\u003c/code\u003e 自己匹配出来。更直接的做法是:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20pgrep%20-af%20gunicorn\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003epgrep -af gunicorn\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e管道默认不传递标准错误:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20%2F%20-name%20'*.conf'%202%3E%2Fdev%2Fnull%20%7C%20head\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind / -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.conf'\u003c/span\u003e 2\u0026gt;/dev/null | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ehead\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"12-3-输出重定向\"\u003e12.3 输出重定向\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20echo%20'DEBUG%3Dfalse'%20%3E%20config.env%20%20%20%20%20%20%20%23%20%E8%A6%86%E7%9B%96%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA%0A%24%20echo%20'PORT%3D8000'%20%3E%3E%20config.env%20%20%20%20%20%20%20%20%23%20%E8%BF%BD%E5%8A%A0%E6%A0%87%E5%87%86%E8%BE%93%E5%87%BA%0A%24%20command%202%3E%20error.log%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E5%8F%AA%E9%87%8D%E5%AE%9A%E5%90%91%E9%94%99%E8%AF%AF%0A%24%20command%20%3E%20output.log%202%3E%20error.log%20%20%20%20%20%23%20%E8%BE%93%E5%87%BA%E5%92%8C%E9%94%99%E8%AF%AF%E5%88%86%E5%BC%80%0A%24%20command%20%3E%20all.log%202%3E%261%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E4%BA%8C%E8%80%85%E5%86%99%E5%85%A5%E5%90%8C%E4%B8%80%E6%96%87%E4%BB%B6%0A%24%20command%20%26%3E%20all.log%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20Bash%20%E7%AE%80%E5%86%99%0A%24%20command%20%3E%20%2Fdev%2Fnull%202%3E%261%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E4%B8%A2%E5%BC%83%E8%BE%93%E5%87%BA%E4%B8%8E%E9%94%99%E8%AF%AF\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eecho\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'DEBUG=false'\u003c/span\u003e \u0026gt; config.env \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 覆盖标准输出\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eecho\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'PORT=8000'\u003c/span\u003e \u0026gt;\u0026gt; config.env \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 追加标准输出\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e 2\u0026gt; error.log \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 只重定向错误\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; output.log 2\u0026gt; error.log \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 输出和错误分开\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; all.log 2\u0026gt;\u0026amp;1 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 二者写入同一文件\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026amp;\u0026gt; all.log \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# Bash 简写\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# 丢弃输出与错误\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e顺序很重要:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20command%20%3E%20all.log%202%3E%261%20%20%20%20%23%20stderr%20%E8%B7%9F%E9%9A%8F%E5%B7%B2%E7%BB%8F%E6%8C%87%E5%90%91%20all.log%20%E7%9A%84%20stdout%0A%24%20command%202%3E%261%20%3E%20all.log%20%20%20%20%23%20stderr%20%E5%85%88%E6%8C%87%E5%90%91%E7%BB%88%E7%AB%AF%EF%BC%8C%E4%B9%8B%E5%90%8E%E5%8F%AA%E6%9C%89%20stdout%20%E6%94%B9%E5%88%B0%E6%96%87%E4%BB%B6\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; all.log 2\u0026gt;\u0026amp;1 \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# stderr 跟随已经指向 all.log 的 stdout\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e 2\u0026gt;\u0026amp;1 \u0026gt; all.log \u003cspan class=\"hljs-comment\" style=\"color:#6a9955;font-style:italic;\"\u003e# stderr 先指向终端,之后只有 stdout 改到文件\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"12-4-输入重定向与-here-document\"\u003e12.4 输入重定向与 Here Document\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20wc%20-l%20%3C%20users.txt%0A4\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -l \u0026lt; users.txt\u003c/span\u003e\n4\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e批量写入多行文本:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20cat%20%3E%20settings.ini%20%3C%3C'EOF'%0A%5Bapp%5D%0Adebug%20%3D%20false%0Aport%20%3D%208000%0AEOF\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ cat \u0026gt; settings.ini \u0026lt;\u0026lt;'EOF'\n[app]\ndebug = false\nport = 8000\nEOF\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e分隔符加单引号后,正文中的 \u003ccode\u003e$变量\u003c/code\u003e 和 \u003ccode\u003e$(命令)\u003c/code\u003e 不会展开。\u003c/p\u003e\n\u003ch3 id=\"12-5-tee\"\u003e12.5 \u003ccode\u003etee\u003c/code\u003e\u003c/h3\u003e\u003cp\u003e既在屏幕显示又保存:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20-E%20'ERROR%7CWARN'%20~%2Flinux-lab%2Flogs%2Fapp.log%20%7C%20tee%20~%2Flinux-lab%2Fbackup%2Fproblems.log%0A2026-07-29%2009%3A03%3A40%20ERROR%20database%20timeout%20request_id%3Dr101%0A2026-07-29%2009%3A04%3A03%20WARN%20%20slow%20request%20cost%3D1.82s%0A2026-07-29%2009%3A05%3A27%20ERROR%20permission%20denied%20path%3D%2Fsrv%2Fapp%2Fupload\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep -E 'ERROR|WARN' ~/linux-lab/logs/app.log | tee ~/linux-lab/backup/problems.log\n2026-07-29 09:03:40 ERROR database timeout request_id=r101\n2026-07-29 09:04:03 WARN slow request cost=1.82s\n2026-07-29 09:05:27 ERROR permission denied path=/srv/app/upload\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e追加使用 \u003ccode\u003etee -a\u003c/code\u003e。写入需要 root 权限的文件时:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20echo%20'127.0.0.1%20forum.local'%20%7C%20sudo%20tee%20-a%20%2Fetc%2Fhosts\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eecho\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'127.0.0.1 forum.local'\u003c/span\u003e | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003esudo\u003c/span\u003e \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etee\u003c/span\u003e -a /etc/hosts\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003esudo echo ... \u0026gt; /etc/hosts\u003c/code\u003e 往往失败,因为重定向由当前普通 Shell 提前完成,\u003ccode\u003esudo\u003c/code\u003e 只作用于 \u003ccode\u003eecho\u003c/code\u003e。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"13-命令连接与退出状态\"\u003e13. 命令连接与退出状态\u003c/h2\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e写法\u003c/th\u003e\n\u003cth\u003e含义\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecmd1 ; cmd2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e无论前者成功与否都执行后者\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecmd1 \u0026amp;\u0026amp; cmd2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e前者成功才执行后者\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e`cmd1\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecmd1 | cmd2\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e前者输出作为后者输入\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20mkdir%20release%20%26%26%20cp%20app.py%20release%2F%0A%0A%5Bmia%40linux%20~%5D%24%20test%20-f%20config.env%20%7C%7C%20echo%20'config.env%20%E4%B8%8D%E5%AD%98%E5%9C%A8'%0Aconfig.env%20%E4%B8%8D%E5%AD%98%E5%9C%A8\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ mkdir release \u0026amp;\u0026amp; cp app.py release/\n\n[mia@linux ~]$ test -f config.env || echo 'config.env 不存在'\nconfig.env 不存在\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003eLinux 命令通常用退出状态表示结果:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e0\u003c/code\u003e:成功;\u003c/li\u003e\n\u003cli\u003e非 \u003ccode\u003e0\u003c/code\u003e:失败或出现特定情况。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20'ERROR'%20~%2Flinux-lab%2Flogs%2Fapp.log%20%3E%2Fdev%2Fnull%0A%5Bmia%40linux%20~%5D%24%20echo%20%24%3F%0A0%0A%0A%5Bmia%40linux%20~%5D%24%20grep%20'FATAL'%20~%2Flinux-lab%2Flogs%2Fapp.log%20%3E%2Fdev%2Fnull%0A%5Bmia%40linux%20~%5D%24%20echo%20%24%3F%0A1\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep 'ERROR' ~/linux-lab/logs/app.log \u0026gt;/dev/null\n[mia@linux ~]$ echo $?\n0\n\n[mia@linux ~]$ grep 'FATAL' ~/linux-lab/logs/app.log \u0026gt;/dev/null\n[mia@linux ~]$ echo $?\n1\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e\u003ccode\u003e$?\u003c/code\u003e 只保存最近一条前台命令的状态,应立即查看。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"14-安全地批量处理文件-xargs\"\u003e14. 安全地批量处理文件:\u003ccode\u003exargs\u003c/code\u003e\u003c/h2\u003e\u003cp\u003e简单形式:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20printf%20'%25s%5Cn'%20a.log%20b.log%20%7C%20xargs%20rm\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eprintf\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'%s\\n'\u003c/span\u003e a.log b.log | xargs \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003erm\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e但文件名可能包含空格或换行,严肃场景使用 NUL 分隔:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20logs%20-type%20f%20-name%20'*.log'%20-print0%20%7C%20xargs%20-0%20grep%20-Hn%20'ERROR'\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind logs -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -print0 | xargs -0 grep -Hn \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e许多场景可直接用 \u003ccode\u003efind -exec ... {} +\u003c/code\u003e,这样不需要额外考虑结果如何传递。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"15-vim-面试够用版\"\u003e15. Vim 面试够用版\u003c/h2\u003e\u003ch3 id=\"15-1-三种主要模式\"\u003e15.1 三种主要模式\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e模式\u003c/th\u003e\n\u003cth\u003e进入方式\u003c/th\u003e\n\u003cth\u003e作用\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e普通模式\u003c/td\u003e\n\u003ctd\u003e打开文件或按 \u003ccode\u003eEsc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e移动、复制、删除、搜索\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e插入模式\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ei\u003c/code\u003e、\u003ccode\u003ea\u003c/code\u003e、\u003ccode\u003eo\u003c/code\u003e 等\u003c/td\u003e\n\u003ctd\u003e输入文字\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e命令行模式\u003c/td\u003e\n\u003ctd\u003e普通模式按 \u003ccode\u003e:\u003c/code\u003e、\u003ccode\u003e/\u003c/code\u003e、\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e保存、退出、搜索、替换\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20vim%20~%2Flinux-lab%2Fapp%2Fconfig.env\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ vim ~/linux-lab/app/config.env\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e最短操作流程:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003etext\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"i%20%20%20%20%20%20%20%20%E8%BF%9B%E5%85%A5%E6%8F%92%E5%85%A5%E6%A8%A1%E5%BC%8F%0A%E8%BE%93%E5%85%A5%E5%86%85%E5%AE%B9%0AEsc%20%20%20%20%20%20%E5%9B%9E%E5%88%B0%E6%99%AE%E9%80%9A%E6%A8%A1%E5%BC%8F%0A%3Awq%20%20%20%20%20%20%E4%BF%9D%E5%AD%98%E5%B9%B6%E9%80%80%E5%87%BA\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-text\"\u003ei 进入插入模式\n输入内容\nEsc 回到普通模式\n:wq 保存并退出\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"15-2-高频按键\"\u003e15.2 高频按键\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e按键\u003c/th\u003e\n\u003cth\u003e作用\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eh j k l\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e左、下、上、右\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e0\u003c/code\u003e / \u003ccode\u003e$\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e行首/行尾\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003egg\u003c/code\u003e / \u003ccode\u003eG\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e文件首/文件尾\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ew\u003c/code\u003e / \u003ccode\u003eb\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下一个/上一个单词\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ei\u003c/code\u003e / \u003ccode\u003ea\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e光标前/后插入\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eo\u003c/code\u003e / \u003ccode\u003eO\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下方/上方新建一行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edd\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e删除/剪切当前行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eyy\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e复制当前行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ep\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e粘贴到光标后\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eu\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e撤销\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eCtrl+r\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e重做\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e/word\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e向下搜索\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003en\u003c/code\u003e / \u003ccode\u003eN\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e下一个/上一个匹配\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003ch3 id=\"15-3-保存-退出与替换\"\u003e15.3 保存、退出与替换\u003c/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003e命令\u003c/th\u003e\n\u003cth\u003e作用\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:w\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e保存\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:q\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e退出\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:wq\u003c/code\u003e 或 \u003ccode\u003eZZ\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e保存并退出\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:q!\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e放弃修改并退出\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:set number\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e显示行号\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:%s/old/new/g\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e全文件替换\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e:%s/old/new/gc\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e全文件替换,每次确认\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\u003chr\u003e\n\u003ch2 id=\"16-高频实战题\"\u003e16. 高频实战题\u003c/h2\u003e\u003ch3 id=\"16-1-统计日志中-error-数量\"\u003e16.1 统计日志中 ERROR 数量\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%5Bmia%40linux%20~%5D%24%20grep%20-c%20'ERROR'%20~%2Flinux-lab%2Flogs%2Fapp.log%0A2\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e[mia@linux ~]$ grep -c 'ERROR' ~/linux-lab/logs/app.log\n2\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e若需要统计匹配结果行数,也可:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20grep%20'ERROR'%20app.log%20%7C%20wc%20-l\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e app.log | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ewc\u003c/span\u003e -l\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"16-2-找出-var-log-下大于-100-mib-的日志\"\u003e16.2 找出 \u003ccode\u003e/var/log\u003c/code\u003e 下大于 100 MiB 的日志\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20sudo%20find%20%2Fvar%2Flog%20-type%20f%20-name%20'*.log'%20-size%20%2B100M%20-print\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003esudo\u003c/span\u003e find /var/log -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -size +100M -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eprint\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"16-3-查找项目中写死的密码字段\"\u003e16.3 查找项目中写死的密码字段\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20grep%20-RniE%20'password%7Csecret%7Ctoken'%20.%2Fproject%20%5C%0A%20%20--exclude-dir%3D.git%20--exclude%3D'*.pyc'\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep -RniE \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'password|secret|token'\u003c/span\u003e ./project \\\n --exclude-dir=.git --exclude=\u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.pyc'\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"16-4-保留最近结果-同时记录错误\"\u003e16.4 保留最近结果,同时记录错误\u003c/h3\u003e\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20python%20manage.py%20migrate%20%3E%20migrate.log%202%3E%261%0A%24%20tail%20-n%2030%20migrate.log\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003epython manage.py migrate \u0026gt; migrate.log 2\u0026gt;\u0026amp;1\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etail\u003c/span\u003e -n 30 migrate.log\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003ch3 id=\"16-5-把最近一天的-log-文件归档到目录\"\u003e16.5 把最近一天的 \u003ccode\u003e.log\u003c/code\u003e 文件归档到目录\u003c/h3\u003e\u003cp\u003e先只查看:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20find%20.%2Flogs%20-type%20f%20-name%20'*.log'%20-mtime%20-1%20-print\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ./logs -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -mtime -1 -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eprint\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003cp\u003e确认后再复制:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20mkdir%20-p%20backup%2Frecent%0A%24%20find%20.%2Flogs%20-type%20f%20-name%20'*.log'%20-mtime%20-1%20-exec%20cp%20-t%20backup%2Frecent%20--%20%7B%7D%20%2B\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003emkdir\u003c/span\u003e -p backup/recent\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind ./logs -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.log'\u003c/span\u003e -mtime -1 -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eexec\u003c/span\u003e \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecp\u003c/span\u003e -t backup/recent -- {} +\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"17-高频面试问答\"\u003e17. 高频面试问答\u003c/h2\u003e\u003ch3 id=\"17-1-绝对路径和相对路径有什么区别\"\u003e17.1 绝对路径和相对路径有什么区别?\u003c/h3\u003e\u003cp\u003e绝对路径从根目录 \u003ccode\u003e/\u003c/code\u003e 开始,不依赖当前目录;相对路径从当前工作目录开始,结果会受 \u003ccode\u003epwd\u003c/code\u003e 影响。\u003c/p\u003e\n\u003ch3 id=\"17-2-和-有什么区别\"\u003e17.2 \u003ccode\u003e\u0026gt;\u003c/code\u003e 和 \u003ccode\u003e\u0026gt;\u0026gt;\u003c/code\u003e 有什么区别?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003e\u0026gt;\u003c/code\u003e 覆盖目标文件,\u003ccode\u003e\u0026gt;\u0026gt;\u003c/code\u003e 追加到文件尾部。两者默认只处理标准输出,错误输出需要使用 \u003ccode\u003e2\u0026gt;\u003c/code\u003e 等写法。\u003c/p\u003e\n\u003ch3 id=\"17-3-管道和重定向有什么区别\"\u003e17.3 管道和重定向有什么区别?\u003c/h3\u003e\u003cp\u003e管道把一个命令的标准输出交给另一个命令的标准输入;重定向改变标准输入、标准输出或标准错误所连接的位置,通常是文件。\u003c/p\u003e\n\u003ch3 id=\"17-4-find-和-grep-的区别\"\u003e17.4 \u003ccode\u003efind\u003c/code\u003e 和 \u003ccode\u003egrep\u003c/code\u003e 的区别?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003efind\u003c/code\u003e 主要按名称、类型、大小、时间等文件属性查找文件;\u003ccode\u003egrep\u003c/code\u003e 主要在文本内容中查找匹配行。两者经常组合使用。\u003c/p\u003e\n\u003ch3 id=\"17-5-which-为什么找不到-cd\"\u003e17.5 \u003ccode\u003ewhich\u003c/code\u003e 为什么找不到 \u003ccode\u003ecd\u003c/code\u003e?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003ecd\u003c/code\u003e 通常是 Shell 内建命令,不是通过 \u003ccode\u003ePATH\u003c/code\u003e 搜索的普通外部程序。使用 \u003ccode\u003etype cd\u003c/code\u003e 能正确识别它。\u003c/p\u003e\n\u003ch3 id=\"17-6-tail-f-与-tail-f-的区别\"\u003e17.6 \u003ccode\u003etail -f\u003c/code\u003e 与 \u003ccode\u003etail -F\u003c/code\u003e 的区别?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003e-f\u003c/code\u003e 持续读取当前文件描述符;\u003ccode\u003e-F\u003c/code\u003e 还会按文件名重试,日志轮转导致原文件被替换时更容易继续追踪。\u003c/p\u003e\n\u003ch3 id=\"17-7-为什么-rm-rf-危险\"\u003e17.7 为什么 \u003ccode\u003erm -rf\u003c/code\u003e 危险?\u003c/h3\u003e\u003cp\u003e\u003ccode\u003e-r\u003c/code\u003e 会递归遍历目录,\u003ccode\u003e-f\u003c/code\u003e 取消确认和多数报错。如果路径、变量或通配符写错,可能快速删除大量数据,而且通常无法从回收站恢复。\u003c/p\u003e\n\u003ch3 id=\"17-8-单引号和双引号有什么区别\"\u003e17.8 单引号和双引号有什么区别?\u003c/h3\u003e\u003cp\u003e单引号基本保留全部字面内容,不展开变量和命令;双引号会展开 \u003ccode\u003e$变量\u003c/code\u003e 和 \u003ccode\u003e$(命令)\u003c/code\u003e,但保留空格并阻止通配展开。\u003c/p\u003e\n\u003ch3 id=\"17-9-21-是什么意思\"\u003e17.9 \u003ccode\u003e2\u0026gt;\u0026amp;1\u003c/code\u003e 是什么意思?\u003c/h3\u003e\u003cp\u003e让文件描述符 2(标准错误)指向文件描述符 1(标准输出)当前指向的位置。它与前后重定向的顺序有关。\u003c/p\u003e\n\u003ch3 id=\"17-10-如何统计出现次数最多的-ip\"\u003e17.10 如何统计出现次数最多的 IP?\u003c/h3\u003e\u003cp\u003e假设访问日志第一列是 IP:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20awk%20'%7Bprint%20%241%7D'%20access.log%20%7C%20sort%20%7C%20uniq%20-c%20%7C%20sort%20-nr%20%7C%20head\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003eawk \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'{print $1}'\u003c/span\u003e access.log | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003esort\u003c/span\u003e | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003euniq\u003c/span\u003e -c | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003esort\u003c/span\u003e -nr | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ehead\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e\u003chr\u003e\n\u003ch2 id=\"18-最终自测\"\u003e18. 最终自测\u003c/h2\u003e\u003cp\u003e不看答案完成以下任务:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e在家目录创建 \u003ccode\u003ereview/{src,logs,backup}\u003c/code\u003e。\u003c/li\u003e\n\u003cli\u003e创建三行日志,其中两行包含 \u003ccode\u003eERROR\u003c/code\u003e。\u003c/li\u003e\n\u003cli\u003e显示日志最后两行并持续跟踪。\u003c/li\u003e\n\u003cli\u003e统计 \u003ccode\u003eERROR\u003c/code\u003e 行数。\u003c/li\u003e\n\u003cli\u003e把标准输出和错误同时保存到 \u003ccode\u003erun.log\u003c/code\u003e。\u003c/li\u003e\n\u003cli\u003e查找当前目录下 24 小时内修改的 \u003ccode\u003e.py\u003c/code\u003e 文件。\u003c/li\u003e\n\u003cli\u003e递归搜索项目中出现 \u003ccode\u003eDEBUG=True\u003c/code\u003e 的文件并显示行号。\u003c/li\u003e\n\u003cli\u003e用一条命令把查询结果同时显示并保存。\u003c/li\u003e\n\u003cli\u003e解释 \u003ccode\u003erm -rf \"$target\"\u003c/code\u003e 中为什么变量必须加双引号,以及为什么执行前仍要验证目标。\u003c/li\u003e\n\u003cli\u003e在 Vim 中完成搜索、替换、保存退出。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e一组参考命令:\u003c/p\u003e\n\u003cdiv class=\"code-block-wrapper\" data-code-rendered=\"true\"\u003e\n \u003cdiv class=\"code-block-header\"\u003e\n \u003cspan class=\"code-lang\"\u003econsole\u003c/span\u003e\n \u003cbutton class=\"code-copy-btn\" data-code=\"%24%20mkdir%20-p%20~%2Freview%2F%7Bsrc%2Clogs%2Cbackup%7D%0A%24%20printf%20'INFO%20start%5CnERROR%20db%5CnERROR%20permission%5Cn'%20%3E%20~%2Freview%2Flogs%2Fapp.log%0A%24%20tail%20-n%202%20-f%20~%2Freview%2Flogs%2Fapp.log%0A%24%20grep%20-c%20'ERROR'%20~%2Freview%2Flogs%2Fapp.log%0A%24%20command%20%3E%20~%2Freview%2Frun.log%202%3E%261%0A%24%20find%20.%20-type%20f%20-name%20'*.py'%20-mtime%20-1%0A%24%20grep%20-RniF%20'DEBUG%3DTrue'%20.%0A%24%20grep%20-n%20'ERROR'%20~%2Freview%2Flogs%2Fapp.log%20%7C%20tee%20~%2Freview%2Fbackup%2Ferrors.txt\"\u003e复制\u003c/button\u003e\n \u003c/div\u003e\n \u003cpre class=\"code-block\"\u003e\u003ccode class=\"hljs language-console\"\u003e\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003emkdir\u003c/span\u003e -p ~/review/{src,logs,backup}\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003eprintf\u003c/span\u003e \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'INFO start\\nERROR db\\nERROR permission\\n'\u003c/span\u003e \u0026gt; ~/review/logs/app.log\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etail\u003c/span\u003e -n 2 -f ~/review/logs/app.log\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep -c \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e ~/review/logs/app.log\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003e\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003ecommand\u003c/span\u003e \u0026gt; ~/review/run.log 2\u0026gt;\u0026amp;1\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003efind . -\u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etype\u003c/span\u003e f -name \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'*.py'\u003c/span\u003e -mtime -1\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep -RniF \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'DEBUG=True'\u003c/span\u003e .\u003c/span\u003e\n\u003cspan class=\"hljs-meta prompt_\" style=\"color:#c586c0;\"\u003e$ \u003c/span\u003e\u003cspan class=\"language-bash\"\u003egrep -n \u003cspan class=\"hljs-string\" style=\"color:#ce9178;\"\u003e'ERROR'\u003c/span\u003e ~/review/logs/app.log | \u003cspan class=\"hljs-built_in\" style=\"color:#4ec9b0;font-weight:600;\"\u003etee\u003c/span\u003e ~/review/backup/errors.txt\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n \u003c/div\u003e","toc":[{"level":1,"text":"Linux 基础命令复习手册","id":"linux-基础命令复习手册"},{"level":2,"text":"1. 高频命令总表","id":"1-高频命令总表"},{"level":3,"text":"必须认识的目录","id":"必须认识的目录"},{"level":2,"text":"2. 先准备一套统一练习数据","id":"2-先准备一套统一练习数据"},{"level":2,"text":"3. Linux 目录树与路径","id":"3-linux-目录树与路径"},{"level":3,"text":"3.1 Linux 只有一棵目录树","id":"3-1-linux-只有一棵目录树"},{"level":3,"text":"3.2 绝对路径与相对路径","id":"3-2-绝对路径与相对路径"},{"level":3,"text":"3.3 特殊路径","id":"3-3-特殊路径"},{"level":3,"text":"3.4 文件名、隐藏文件与大小写","id":"3-4-文件名-隐藏文件与大小写"},{"level":2,"text":"4. 命令的基本结构","id":"4-命令的基本结构"},{"level":3,"text":"4.1 如何查帮助","id":"4-1-如何查帮助"},{"level":2,"text":"5. 查看目录:ls","id":"5-查看目录-ls"},{"level":2,"text":"6. 创建目录和文件","id":"6-创建目录和文件"},{"level":3,"text":"6.1 mkdir","id":"6-1-mkdir"},{"level":3,"text":"6.2 touch","id":"6-2-touch"},{"level":3,"text":"6.3 file 与 stat","id":"6-3-file-与-stat"},{"level":2,"text":"7. 查看文件内容","id":"7-查看文件内容"},{"level":3,"text":"7.1 怎么选命令","id":"7-1-怎么选命令"},{"level":3,"text":"7.2 cat","id":"7-2-cat"},{"level":3,"text":"7.3 less","id":"7-3-less"},{"level":3,"text":"7.4 head 与 tail","id":"7-4-head-与-tail"},{"level":2,"text":"8. 复制、移动与删除","id":"8-复制-移动与删除"},{"level":3,"text":"8.1 cp","id":"8-1-cp"},{"level":3,"text":"8.2 mv","id":"8-2-mv"},{"level":3,"text":"8.3 rm","id":"8-3-rm"},{"level":3,"text":"8.4 删除前的安全习惯","id":"8-4-删除前的安全习惯"},{"level":2,"text":"9. 通配符、引号与命令替换","id":"9-通配符-引号与命令替换"},{"level":3,"text":"9.1 通配符","id":"9-1-通配符"},{"level":3,"text":"9.2 单引号、双引号与不加引号","id":"9-2-单引号-双引号与不加引号"},{"level":3,"text":"9.3 命令替换","id":"9-3-命令替换"},{"level":2,"text":"10. 查找命令与文件","id":"10-查找命令与文件"},{"level":3,"text":"10.1 type、command -v、which","id":"10-1-type-command-v-which"},{"level":3,"text":"10.2 find 基本结构","id":"10-2-find-基本结构"},{"level":2,"text":"11. 文本过滤与统计","id":"11-文本过滤与统计"},{"level":3,"text":"11.1 grep","id":"11-1-grep"},{"level":3,"text":"11.2 wc","id":"11-2-wc"},{"level":3,"text":"11.3 sort、uniq、cut","id":"11-3-sort-uniq-cut"},{"level":2,"text":"12. 管道与重定向","id":"12-管道与重定向"},{"level":3,"text":"12.1 三个标准流","id":"12-1-三个标准流"},{"level":3,"text":"12.2 管道 |","id":"12-2-管道"},{"level":3,"text":"12.3 输出重定向","id":"12-3-输出重定向"},{"level":3,"text":"12.4 输入重定向与 Here Document","id":"12-4-输入重定向与-here-document"},{"level":3,"text":"12.5 tee","id":"12-5-tee"},{"level":2,"text":"13. 命令连接与退出状态","id":"13-命令连接与退出状态"},{"level":2,"text":"14. 安全地批量处理文件:xargs","id":"14-安全地批量处理文件-xargs"},{"level":2,"text":"15. Vim 面试够用版","id":"15-vim-面试够用版"},{"level":3,"text":"15.1 三种主要模式","id":"15-1-三种主要模式"},{"level":3,"text":"15.2 高频按键","id":"15-2-高频按键"},{"level":3,"text":"15.3 保存、退出与替换","id":"15-3-保存-退出与替换"},{"level":2,"text":"16. 高频实战题","id":"16-高频实战题"},{"level":3,"text":"16.1 统计日志中 ERROR 数量","id":"16-1-统计日志中-error-数量"},{"level":3,"text":"16.2 找出 /var/log 下大于 100 MiB 的日志","id":"16-2-找出-var-log-下大于-100-mib-的日志"},{"level":3,"text":"16.3 查找项目中写死的密码字段","id":"16-3-查找项目中写死的密码字段"},{"level":3,"text":"16.4 保留最近结果,同时记录错误","id":"16-4-保留最近结果-同时记录错误"},{"level":3,"text":"16.5 把最近一天的 .log 文件归档到目录","id":"16-5-把最近一天的-log-文件归档到目录"},{"level":2,"text":"17. 高频面试问答","id":"17-高频面试问答"},{"level":3,"text":"17.1 绝对路径和相对路径有什么区别?","id":"17-1-绝对路径和相对路径有什么区别"},{"level":3,"text":"17.2 \u003e 和 \u003e\u003e 有什么区别?","id":"17-2-和-有什么区别"},{"level":3,"text":"17.3 管道和重定向有什么区别?","id":"17-3-管道和重定向有什么区别"},{"level":3,"text":"17.4 find 和 grep 的区别?","id":"17-4-find-和-grep-的区别"},{"level":3,"text":"17.5 which 为什么找不到 cd?","id":"17-5-which-为什么找不到-cd"},{"level":3,"text":"17.6 tail -f 与 tail -F 的区别?","id":"17-6-tail-f-与-tail-f-的区别"},{"level":3,"text":"17.7 为什么 rm -rf 危险?","id":"17-7-为什么-rm-rf-危险"},{"level":3,"text":"17.8 单引号和双引号有什么区别?","id":"17-8-单引号和双引号有什么区别"},{"level":3,"text":"17.9 2\u003e\u00261 是什么意思?","id":"17-9-2-1-是什么意思"},{"level":3,"text":"17.10 如何统计出现次数最多的 IP?","id":"17-10-如何统计出现次数最多的-ip"},{"level":2,"text":"18. 最终自测","id":"18-最终自测"}],"history":[]}},"postRelatedBySlug":{"Linux-基础命令复习手册":{"posts":[{"id":1,"title":"V2Ray 客户端使用教程:Windows 和 Android 的导入、切换与常见设置","slug":"v2ray-guide","excerpt":"直接复制链接到客户端里导入","cover_image":"/article-default-cover.png","published_at":"2026-06-05T09:43:20.308Z","first_published_at":"2026-04-26T12:42:52.363497Z","cover_image_sources":{"src":"/article-default-cover.png","sources":[],"sizes":"(max-width: 768px) 100vw, 760px"}},{"id":2,"title":"优选 CDN IP 使用教程:用 cfst 筛出最快的节点","slug":"cdn-ip-guide","excerpt":"使用CDN IP加速,速度提升显著,稳定性一般","cover_image":"/uploads/posts/cdn-ip-guide/cover.svg","published_at":"2026-06-05T09:40:02.456Z","first_published_at":"2026-04-26T13:58:53.244Z","cover_image_sources":{"src":"/uploads/posts/cdn-ip-guide/cover.svg","sources":[],"sizes":"(max-width: 768px) 100vw, 760px"}},{"id":87,"title":"MySQL 进阶复习手册(理解强化版)","slug":"MySQL-进阶复习手册-理解强化版","excerpt":"MySQL 进阶复习手册(理解强化版) 适用范围:MySQL 8.0 / 8.4,默认存储引擎为 InnoDB。 定位:这不是 PDF 的缩写版,而是按理解顺序重新编写的复习与实验手册。 约定:SQL 关键字大写,表名与列名使用 snakecase;终端结果只保留能说明问题的行。 最重要的学习顺序:InnoDB → 事务与 MVCC → 索引 → 执行计划 → SQL 优化 →...","cover_image":null,"published_at":"2026-07-30T07:11:10.815Z","first_published_at":"2026-07-30T07:11:10.815Z","cover_image_sources":null},{"id":86,"title":"MySQL 基础复习手册(强化校订版)","slug":"MySQL-基础复习手册-强化校订版","excerpt":"MySQL 基础复习手册(强化校订版) 适用范围:MySQL 8.x。目标是复习 SQL、准备 Python 开发面试,而不是照抄安装教程。 使用方法:先浏览第 0 章的五张表;需要动手时执行初始化脚本。后文所有命令都基于同一批数据。 约定:SQL 关键字大写,表名和字段名使用小写 snakecase;结果集只展示能说明问题的列和行。 目录 - 0. 统一示例数据库0-统一示例数据...","cover_image":null,"published_at":"2026-07-30T07:10:30.958Z","first_published_at":"2026-07-30T07:10:30.958Z","cover_image_sources":null},{"id":53,"title":"进程线程协程","slug":"408-进程线程协程","excerpt":"进程线程协程 1. 一句话总结 进程是资源分配单位,线程是 CPU 调度单位,协程是用户态调度的轻量执行单元。 2. 通俗解释 进程像独立公司,有自己的资产和空间;线程像公司员工,共享公司资源但各自有工作栈;协程像员工手动切换手头任务,切换更轻。 3. 核心概念 - 进程:拥有独立地址空间和系统资源。 - 线程:进程内执行流,共享进程资源。 - 协程:由程序或运行时在用户态调度。 - 并发:...","cover_image":null,"published_at":"2026-05-28T15:24:54.464Z","first_published_at":"2026-05-28T15:24:54.464Z","cover_image_sources":null}]}},"series":{"series":[{"id":3,"name":"408","slug":"408","description":"计算机基础 408 面试与复习课程。","cover_image":null,"sort_order":0,"post_count":49}]}},"generatedAt":1785398743079}