head -n 20取前20行,tail -n 20取后20行;head -n -5排除末尾5行,tail -n +5从第5行起输出至末尾;组合取100–150行应为tail -n +100 file | head -n 50。

head -n 和 tail -n 行数参数怎么写才不翻车
直接说结论:head -n 20 是取前 20 行,tail -n 20 是取后 20 行,但负数和加号含义完全不同,写错就完全反了。
常见错误是把 head -n -5 当成“跳过前 5 行”,其实它是“排除末尾 5 行”;而 tail -n +5 才是“从第 5 行开始往后全取”。这两个符号必须记死:
-
head -n -N:去掉文件末尾 N 行,保留前面所有(不是跳过) -
tail -n +N:从第 N 行起,输出到文件末尾(含第 N 行) -
tail -n N:只取最后 N 行(默认行为,等价于tail -n +$(wc -l )
别依赖默认值——哪怕只是查前 1 行,也写 head -n 1,避免不同系统或 shell 环境下行为差异。
想看第 100–150 行?别用 sed,用 tail + head 组合
对大文件来说,sed -n '100,150p' 要逐行解析、状态判断,而 tail -n +100 file | head -n 50 是流式处理:tail 从末往前找换行符定位起始位置,head 只计数 50 行就停,内存和时间都更省。
实操要点:
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
- 顺序不能反:
head -n 150 file | tail -n 50也能出结果,但会先把前 150 行全读进内存,对 GB 级日志就是浪费 - 确保每行以
\n结尾:如果最后一行没换行符,tail -n +100可能少输出一行(POSIX 行为) - 想跳过前 3 行再取 10 行?写
tail -n +4 file | head -n 10,不是head -n 10 file | tail -n +4
tail -f 实时监控时为什么不动了?大概率是 logrotate 搞的鬼
tail -f 跟的是 inode,不是文件名。logrotate 把 app.log 重命名为 app.log.1 并新建空 app.log 后,tail -f 还在盯旧 inode,自然卡住。
生产环境必须用 tail -F(大写 F),它等价于 --follow=name --retry,会检测文件是否被删/重命名,并自动 reopen 新文件。
其他容易忽略的点:
-
tail -f -n 0 app.log:只输出新增行,不刷屏历史内容,上线排查时更干净 - 程序写日志没 flush 或没加
\n(比如 C 的printf("log");),tail -f就收不到——它只认换行作为“一行结束” - macOS 自带 tail 不支持
-F,得装coreutils用gtail
二进制文件或超长单行 JSON 里用 head/tail 会崩
这两个命令本质是按换行符切割文本,遇到非文本内容就不可靠:
- 对
.png或.zip执行head file.png,可能输出乱码甚至卡终端(含控制字符);真要看头几十字节,用head -c 32 file.png或xxd -l 32 file.png - 一行超过 2MB(glibc 行缓冲上限),
head -n 1可能失败并报Argument list too long,这不是权限问题,是 malloc 分配失败 - JSON 日志单行几 MB 且无换行?
tail -n 1会尝试从末尾反向扫描到文件头,慢到超时甚至 OOM;此时应先用jq或awk预处理
最易被忽略的点:你认为的“行”,未必是 head/tail 认的“行”——换行符在哪,它们的边界就在哪。










