在shell脚本中安全获取gzip压缩后文件大小,需先确保gzip成功执行(检查$?或用if gzip命令),再用stat -c "%s" "$gzfile"读取字节数,避免ls、wc或gzip -l等不可靠方法。

在 Shell 脚本中安全获取 gzip 压缩后文件的大小,关键不是“压缩过程中实时读取”,而是**压缩完成后再准确、可靠地获取目标文件(.gz)的字节数**。因为 gzip 本身不输出压缩后大小到 stdout/stderr,需依赖外部命令查询结果文件。
确认压缩成功后再获取大小
不能假设 gzip file.txt 一定成功——网络中断、磁盘满、权限不足都会导致失败。必须检查退出状态:
- 用
gzip -c file.txt > file.txt.gz或gzip file.txt后,立即执行if [ $? -eq 0 ]; then ... fi - 更稳妥写法:
if gzip file.txt; then echo "ok"; else echo "fail"; exit 1; fi
用 stat 安全读取 .gz 文件大小
stat 比 ls -l 更可靠(不受 locale、列宽、别名干扰),推荐使用:
-
size=$(stat -c "%s" "file.txt.gz" 2>/dev/null)—— 返回纯数字,失败时静默返回空 - 加判断:
if [ -n "$size" ] && [ "$size" -ge 0 ] 2>/dev/null; then echo "size: $size bytes"; fi - 注意:不要用
wc -c file.txt.gz,它会多读一个换行符(如果文件末尾无换行,wc仍计为 1 字节额外开销,不精确)
处理原始文件名动态变化的场景
若脚本接受任意路径(如 ./compress.sh /var/log/app.log),需自动构造 .gz 名:
src="$1"; gzfile="${src}.gz"- 或更健壮:
gzfile=$(printf '%s' "$src" | sed 's/[[:space:]]*$//' | sed 's/$/.gz/')(防拖尾空格) - 再配合
stat -c "%s" "$gzfile"获取大小,全程引用变量避免空格/特殊字符出错
避免常见陷阱
以下做法不安全或不可靠:
-
ls -l file.gz | awk '{print $5}':列顺序可能因 ls 配置变动;含中文或特殊权限时格式错乱 -
$(gzip -l file.gz | tail -1 | awk '{print $2}'):仅适用于已存在 .gz 文件,且gzip -l显示的是“压缩前大小”,不是你想要的“.gz 文件自身大小” - 未检查
stat是否存在或是否对文件有读权限(stat在多数 Linux 发行版默认可用,但 Alpine 等精简系统需装coreutils)











