用 head -n 参数可灵活控制行数:正数取前n行,负数排除末尾n行;跳过前m行需结合 tail -n +m 与 head;大文件慎用超大 -n 值,超长行可能导致失败。

查看文件开头几行用 head,但默认 10 行不够用怎么办
head 默认只输出前 10 行,实际中经常要查前 5 行、前 1 行(比如看 CSV 表头),或跳过开头若干行再取。关键靠 -n 参数控制行数,支持正负两种写法:
-
head -n 5 file.txt:取前 5 行 -
head -n -3 file.txt:排除最后 3 行,即取“除末尾三行外的所有行”——这个容易误以为是“从第 3 行开始”,其实不是 - 想跳过前 2 行再取 5 行?
tail -n +3 file.txt | head -n 5,不能只用head实现 - 大文件慎用
head -n 1000000,虽然快,但若行极长(如单行 JSON),仍可能卡住——本质是按换行符读,不是按字节截
用 tail 实时跟踪日志,但 -f 卡住或不刷新
tail -f 是运维最常用的实时监控手段,但它依赖文件是否被“追加写入”且内核缓冲是否及时刷出。常见问题不是命令写错,而是场景不匹配:
- 程序用
printf写日志但没加\n,或开了全缓冲(如 C 的setvbuf),tail -f就看不到——因为没换行,tail不认为是“新行” - 日志文件被轮转(logrotate)后,
tail -f会停在原 inode,不再跟随新文件。应改用tail -F(大写 F),它能检测文件重命名/重建并自动 reopen -
tail -f -n 0 file.log表示“从当前末尾开始监听”,避免刷屏历史内容;而-n 20是先输出最后 20 行再监听 - 某些容器环境(如 Docker)日志驱动为
json-file,直接tail -f /var/lib/docker/containers/xxx/xxx-json.log可能乱码,因每行是完整 JSON——这时需要jq配合解析
head 和 tail 处理二进制文件或超长行会出什么问题
这两个命令设计初衷是处理文本,遇到非文本内容时行为不可靠:
- 对二进制文件(如
.png、.zip)执行head file.png,可能输出乱码甚至卡终端(尤其含 ANSI 转义序列时)。真要查二进制头,用xxd -l 32 file.png或od -N 32 -c file.png - 某行超 2MB(glibc 默认行缓冲上限),
head -n 1可能失败并报head: cannot open 'file' for reading: Argument list too long——这不是权限问题,是内部 malloc 失败 -
tail -n 1在超大文件上依然很快,因为它从文件末尾反向找换行符,不加载全文;但若最后一行本身超长且无换行,tail会尝试读到文件头,变慢甚至 OOM - 跨平台注意:macOS 的
tail不支持-F(需用brew install coreutils换成gtail)
管道中组合使用 head/tail 时顺序和性能陷阱
很多人习惯把 head 放管道前面“提前截断”,但顺序错了反而更慢:
-
cat huge.log | head -n 100 | grep ERROR:看似合理,实则cat还是得读完整个文件(除非head能让上游感知 EOF 并退出)。正确做法是head -n 100 huge.log | grep ERROR,让head直接打开文件并只读前 N 行 -
tail -n +100 file.txt | head -n 10等价于“跳过前 99 行,取接下来 10 行”,但比sed -n '100,109p'多一次进程调度,小文件无所谓,高频调用建议压成单条sed或awk - 用
tail -n +2去掉第一行(如 CSV 表头)很常见,但如果文件只有 1 行,结果为空——不会报错,容易静默丢失数据,脚本里需加if [ $(wc -l 判断
真正麻烦的不是语法,是当文件没有换行符、被并发写入、或者路径指向符号链接时,head 和 tail 的行为会偏离直觉。动手前先 file file.txt 看类型,再 stat file.txt 看 inode 和 size 变化趋势,比硬试更省时间。











