核心内容摘要
“四川BBBBBB搡BBBBB事件”
【Linux指南】Linux 命令行进度条
实现原理解析Linux 命令行终端中的进度条如 wget、dd、pv、curl --progress-bar、各种部署脚本等看到的动态条本质上不是图形控件而是纯文本 终端控制技巧的组合。
核心原理一览从浅到深层级
关键技术作用是否必须常见实现方式典型工具/库示例基础\r回车Carriage Return光标回到本行开头不换行★必须printf ...\r或echo -ne ...\r所有 shell 进度条基础不输出\n避免换行让后续输出覆盖本行★必须echo -n/printf不带换行—重要强制刷新缓冲区让终端立即显示而不是等到行结束强烈推荐fflush(stdout)/stdout.flush()C/Python 中常见shell 较少需进阶ANSI 转义码控制颜色、光标移动、清除行、清屏等可选\e[31m红色、\e[2K清行等彩色进度条、多行进度进阶tput / stty / tput cols获取终端宽度、高度、隐藏光标等推荐tput cols、tput civis自适应宽度、隐藏闪烁光标高级ncurses / dialog / whiptail完整 TUI文本用户界面框架—绘制窗口、进度条、菜单dialog --gauge、whiptail高级伪图形字符Unicode更美观的块状进度条可选█ ▓ ░ 等modern cli-progress、rich 等最核心的技巧\r 不换行 覆盖重绘几乎所有简单进度条都依赖这个模式# 原理演示最简版foriin{
.100};do# 构建当前这一帧要显示的内容bar$(printf%-${i}s|tr #)# 填充 #empty$(printf%$((100-i))s |tr -)# 剩余 -# \r 回到行首 -n 不换行 立即显示printf\r[%s%s] %d%%$bar$empty$isleep
08doneecho# 最后换一行关键点解释\r把光标拉回本行第1列后续字符直接覆盖旧内容终端默认行为如果新内容比旧内容短 → 旧的残留字符不会自动清除 → 需要补空格或用\e[2K清行更健壮的写法自适应终端宽度 颜色 隐藏光标#!/usr/bin/env bash# progress.sh# 隐藏光标tput civis# 捕获退出时恢复光标traptput cnorm; echoEXITwidth$(tput cols)# 当前终端列宽((bar_widthwidth-
)# 留空间给百分比和边框total100for((i0;itotal;i));dodone_len$((i*bar_width/total))todo_len$((bar_width-done_len))# 构建进度条bar$(printf%${done_len}s|tr █)empty$(printf%${todo_len}s|tr ░)# 彩色 清行 重绘printf\r\e[2K\e[32m[%s%s]\e[0m %3d%%$bar$empty$isleep
05doneecho-e\nDone.不同语言/场景下的典型实现对比语言/环境核心语句示例刷新方式推荐库/工具Bash / Shellprintf \r[%-50s] %d%% $bar $pct依赖终端行缓冲pv, dialog, whiptailC语言printf(\r[%.*s%*s] %d%%, done, #, todo, , pct); fflush(stdout);fflush(stdout)强制—Pythonprint(f\r[{bar}] {pct}%, end, flushTrue)flushTrue或sys.stdout.flush()tqdm (最流行), rich, alive-progressGofmt.Printf(\r[%s%s] %d%%, bar, space, pct)默认刷新 bufiouiprogress, schollz/progressbarNode.jsprocess.stdout.write(\r[${bar}] ${pct}%)默认行缓冲需 clearLineprogress, cli-progress
常见问题与解决方案生产环境踩坑
总结问题现象原因解决方案进度条残留字符旧进度没被完全覆盖新字符串比旧的短每次先输出\e[2K清整行或补满空格重定向到文件后全是垃圾文件里重复了很多行\r在文件里不会覆盖只追加检测是否是终端[[ -t 1 ]])否则不输出进度进度条闪烁严重光标一直在动没隐藏光标tput civis/tput cnormSSH/远程终端很卡更新很慢或乱码网络延迟 频繁重绘降低刷新频率
2~
5s一次多进度条/多任务显示互相覆盖都写同一行用 ncurses、tput cup 定位多行或用 rich/tqdm的多条支持
总结一句话Linux 命令行进度条的核心只有一句话“用\r反复把光标拉回行首然后覆盖重绘同一行内容并尽量让每次输出长度一致或主动清行。
”掌握这个技巧后你可以轻松实现 wget 风格的下载进度条、make 编译进度、rsync 传输进度、自定义部署脚本的 loading 动画等。
你现在是想自己写一个特定样式的进度条单色/彩色/旋转loading/估计剩余时间集成到某个具体脚本里比如循环、pv 替代、后台任务了解更高级的多行 TUI如 bottom 进度 日志告诉我具体需求我可以直接给你对应代码模板或更深入的实现。