1. cat: 输出文件全部内容
cat 取自 concatenate(连接). 它的本职是把多个文件的内容连接起来输出,但日常中 90% 的用法是快速看一眼某个文件的内容.
1.1 基础用法
|
什么时候不该用 cat: 文件很大(几百 MB)时,cat 会把整个文件内容倾倒到终端,屏幕疯狂滚动. 这时应该用 less.
1.2 常用选项
| 选项 | 含义 | 适用场景 |
|---|---|---|
-n |
显示行号(含空行) | 代码审查,讨论时引用行号 |
-b |
显示行号(跳过空行) | 只看有内容的行的编号 |
-s |
压缩连续空行(squeeze) | 日志文件有大量空行时 |
-A |
显示所有不可见字符 | 排查文件中的怪字符(\r, \t, 行尾空格) |
-E |
在每行末尾显示 $ |
排查行尾空格(只显示行尾标记) |
-T |
Tab 显示为 ^I |
区分 Tab 和空格 |
|
cat 的现代替代: bat
bat(brew install bat)是一个带语法高亮, 行号, Git 变更标记的 cat 增强版. 日常看代码用 bat,管道中传输数据用 cat. alias cat=bat 是很多人的第一行配置.
1.3 输入输出重定向速览
cat 的几个例子中出现了 >, << 等符号. 这些是 Shell 的重定向操作符--控制命令的 stdin(输入)和 stdout/stderr(输出)从哪里来, 到哪里去. 下面是完整的操作符列表:
| 操作符 | 方向 | 作用 | 例子 |
|---|---|---|---|
cmd > file |
stdout → 文件 | 覆盖写入(文件原有内容被清空) | echo hello > a.txt |
cmd >> file |
stdout → 文件 | 追加写入(保留原有内容) | echo world >> a.txt |
cmd < file |
文件 → stdin | 从文件读取输入 | wc -l < data.txt |
cmd << MARKER |
多行文本 → stdin | heredoc: 把后续多行直到 MARKER 作为输入 | cat << EOF > config.yaml |
cmd <<< "string" |
字符串 → stdin | herestring: 把单行字符串作为输入 | grep foo <<< "hello foo bar" |
cmd 2> file |
stderr → 文件 | 把错误输出写入文件 | ls /nope 2> errors.log |
cmd &> file |
stdout + stderr → 文件 | 标准输出和错误输出都写入同一个文件 | npm install &> build.log |
几个具体例子来感受区别:
|
更详细的管道与重定向将在第 10 篇展开.
2. less: 分页浏览(主力文件查看器)
less 是最该熟练掌握的命令之一. 它把文件内容分页显示,让人前后翻页, 搜索, 跳转--全部通过键盘完成.
名字的由来: Unix 最早的分页器叫 more,只能向前翻. 后来有人写了一个能向后翻的增强版,讽刺地取名 less("less is more"--少即是多).
2.1 导航快捷键
| 按键 | 行为 | 记忆 |
|---|---|---|
j / ↓ |
向下滚动一行 | vim 同款 |
k / ↑ |
向上滚动一行 | vim 同款 |
Space / f |
向下翻一屏(forward) | forward |
b |
向上翻一屏(backward) | backward |
d |
向下翻半屏 | half-down |
u |
向上翻半屏(undo-like) | half-up |
g |
跳到文件开头 | go to start |
G |
跳到文件末尾 | Go to end |
50g / 50G |
跳到第 50 行 | 数字 + g/G |
50p / 50% |
跳到文件的 50% 位置 | percent |
q |
退出 | quit |
2.2 搜索
| 按键 | 行为 |
|---|---|
/pattern |
向下搜索 pattern(Enter 确认) |
?pattern |
向上搜索 pattern |
n |
跳转到下一个匹配(next) |
N |
跳转到上一个匹配(Previous) |
&pattern |
只显示包含 pattern 的行(相当于 grep) |
/ 搜索支持正则表达式,且搜索结果会高亮显示. 按 ESC u 可以关闭当前搜索的高亮.
2.3 常用命令行选项
| 选项 | 含义 | 适用场景 |
|---|---|---|
-N |
显示行号 | 讨论日志时用行号精确引用 |
-S |
不自动换行(chop long lines) | 看日志/CSV/JSON 时水平滚动 |
-R |
保留 ANSI 颜色代码 | 看带颜色的命令输出(`grep --color |
-F |
内容少于一屏时自动退出 | 模拟 cat 的行为(less -F = 智能 cat) |
-i |
搜索时忽略大小写 | 不知道确切大小写时 |
+F |
启动后立即进入 follow 模式 | 相当于 tail -f 但可以用 less 的导航功能 |
+50 |
打开文件后直接跳到第 50 行 | 精确定位 |
|
less 之于文本文件,就像 PDF 阅读器之于 PDF.
可以翻页, 搜索, 跳转, 缩放(折行/不折行),但它不修改文件内容.
按 h 可以看 less 的完整帮助--less 的功能远比这里列的更多.
3. head 与 tail: 看头看尾
3.1 head: 输出文件的前几行/字节
|
实际中常与管道配合:
|
3.2 tail: 输出文件的后几行/字节
|
3.3 tail -f: 实时追踪文件增长
tail -f(follow)是运维和开发中最常用的调试手段--实时查看日志文件的追加内容.
|
tail -f 的原理: 它监听文件的 inode. 当日志轮转工具把 app.log 改名并创建新文件时,-f 还在盯旧的 inode,新的日志就看不到了. -F 会检测文件名是否重新出现并自动切换.
4. find: 文件搜索的瑞士军刀
find 是最强大也最容易被 "只记一个 -name" 的文件搜索工具. 它遍历指定目录,对每个文件逐一检查设定的条件,并可对匹配的文件执行操作.
基本语法: find <搜索路径> <条件> [操作]
macOS 的 find 是 BSD 版本
以下所有选项在 macOS 和 Linux 上都通用. BSD find 和 GNU find 在少数高级选项上有差异(如 -printf 仅 GNU 支持),但日常用到的选项两者完全一致.
4.1 按名称搜索
|
通配符必须用引号包起来. 如果不加引号(find . -name *.html),Shell 会先把 *.html 展开为当前目录下的匹配文件,传到 find 时已经不是通配符了.
4.2 按类型搜索
|
4.3 按大小搜索
|
大小单位: c 字节, k KB, M MB, G GB. 注意大小写: k 是小写,M 和 G 是大写.
4.4 按时间搜索
时间条件最容易被搞混. 三个时间维度 + 三种比较方式 = 9 个选项:
| atime(访问时间) | mtime(修改时间) | ctime(元数据变更时间) | |
|---|---|---|---|
| < N 天 | -atime -N |
-mtime -N |
-ctime -N |
| 恰好 N 天 | -atime N |
-mtime N |
-ctime N |
| > N 天 | -atime +N |
-mtime +N |
-ctime +N |
mtime vs ctime 的区别: mtime 是文件内容被修改的时间,ctime 是文件元数据(权限, 所有者, 链接数)变更的时间. 修改文件内容会同时更新 mtime 和 ctime,但 chmod 只更新 ctime.
更精确的时间控制用 -mmin(分钟):
|
4.5 执行操作: -exec 与 -delete
找到文件后,最常用的两个后续操作:
|
\; vs +: \; 对每个文件执行一次命令(如找到 100 个文件就执行 100 次),+ 把所有文件一次传给命令(类似于 xargs,只执行一次或少数几次). 能用 + 就用 +,效率高得多.
4.6 组合条件
|
find 高频组合速查:
| 场景 | 命令 |
|---|---|
| 代码库中找某文件 | find . -name "Dockerfile" |
| 找最近改的文件 | find . -mmin -30 -type f |
| 找大文件清理空间 | find . -size +500M -exec ls -lh {} \; |
| 删除所有 .DS_Store | find . -name ".DS_Store" -delete |
| 跳过 node_modules | find . -not -path "*/node_modules/*" -name "*.js" |
| 统计每种文件数量 | find . -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn |
| 批量修改权限 | find . -name "*.sh" -exec chmod +x {} + |
5. locate: 文件名速查
locate 和 find 的区别: find 是实时遍历文件系统,locate 是查询预建的数据库. 后者快一个数量级但有延迟.
|
locate 的数据库: macOS 上由 /System/Library/LaunchDaemons/com.apple.locate.plist 管理,定期更新(通常每周一次). 数据库位于 /var/db/locate.database. 可以手动更新:
|
| find | locate | |
|---|---|---|
| 速度 | 慢(实时遍历磁盘) | 极快(查数据库) |
| 实时性 | 实时 | 有延迟(数据库快照) |
| 条件丰富度 | 极丰富(大小, 时间, 权限...) | 仅文件名 |
| 适用场景 | 精确搜索, 批量操作 | "我记得有个文件叫 xxx,但忘了在哪" |
现代替代: fd 和 fzf
fd(brew install fd)是 find 的现代化替代--语法更直观,默认尊重 .gitignore,自带颜色输出. fzf 是模糊搜索,交互式实时过滤. 对于日常开发,这两个工具组合比 find 更高效.
快速回顾
- cat = 全部输出; cat -A 是照妖镜(显示隐藏字符); 大文件别用 cat,用 less
- less = 分页浏览器:
j/k上下滚,/pattern搜索,g/G跳头尾,q退出,less +F相当于 tail -f - head -n 20 看前 20 行,head -n -5 去掉最后 5 行
- tail -n 20 看最后 20 行,tail -f 实时追踪(
-F容忍日志轮转) - find 语法: 路径 + 条件 + 操作;
-name/-iname文件名,-type f/d类型,-size +100M大小,-mtime -7时间 - find -delete 或
-exec ... {} +执行操作 - locate 从数据库秒查文件名; find 实时遍历,locate 有延迟但极快
动手练习
- 检查隐藏字符: 用
cat -A ~/.zshrc检查文件中是否有行尾空格或 Tab 混用 - less 导航: 用
less -NS打开一个大文件,练习/pattern搜索,n/N跳转,&过滤 - 实时追踪日志: 用
tail -f追踪一个正在写入的日志文件(或tail -f /var/log/system.log看系统日志) - 按时间找文件: 找出项目目录中最近 30 分钟修改的所有
.html文件 - 找大文件: 找出家目录下大于 100MB 的文件,用人类可读的格式列出
- 对比速度: 用
locate zshrc找系统中所有 zshrc 相关文件,对比find / -name "*zshrc*"的速度差异