如何在Linux Bash中原地替换Zip文件内文件扩展名?
批量修改Zip包内文件扩展名的问题与解决
问题背景
需要批量修改Zip文件内指定文件的扩展名(比如将.pdg替换为.png),直接通过十六进制替换扩展名存在极低的误替换二进制数据概率。尝试在Termux的Bash环境中用zipnote工具实现,却遇到临时文件创建失败的问题。
原脚本与报错信息
原脚本试图通过zipinfo筛选目标文件,生成zipnote可识别的重命名指令:
# There is no /tmp dir in termux. A local temp folder is created mkdir tmp zipinfo -1 $1 |ack .pdg |while read n; do echo @ $n; echo @=${n%.pdg}.png; echo '@ (zip file comment below this line)'; done | zipnote -w -b ./tmp $1
执行时出现如下错误:
zipnote error: Bad file descriptor zipnote error: Temporary file failure
问题原因
Termux环境中zipnote的-b参数对临时目录的路径处理存在兼容性问题,手动创建的./tmp目录可能因权限、路径解析等原因导致zipnote无法正常写入临时文件。
修正后的Bash方案
改用系统原生的临时目录创建方式,同时优化脚本的兼容性:
# 创建安全临时目录 TMP_DIR=$(mktemp -d) # 生成重命名指令并执行 zipinfo -1 "$1" | grep "\.pdg$" | while read -r n; do echo "@ $n" echo "@=${n%.pdg}.png" echo '@ (zip file comment below this line)' done | zipnote -w -b "$TMP_DIR" "$1" # 清理临时目录 rm -rf "$TMP_DIR"
- 用
mktemp -d创建系统级临时目录,避免手动创建的权限和路径问题 - 替换
ack为grep,适配Termux默认环境 - 给变量加引号,兼容含空格的文件名
Python替代方案
如果Bash工具仍存在兼容性问题,用Python的zipfile模块可以更可靠地解决问题,完全避免二进制误替换风险:
import zipfile import os from pathlib import Path def rename_ext_in_zip(zip_path, old_ext, new_ext): tmp_zip = Path(zip_path).parent / f"{Path(zip_path).stem}_temp.zip" # 读取原Zip包并写入临时Zip包 with zipfile.ZipFile(zip_path, 'r') as z_in, zipfile.ZipFile(tmp_zip, 'w') as z_out: for entry in z_in.infolist(): if entry.filename.endswith(old_ext): # 替换扩展名后写入新文件 new_name = entry.filename[:-len(old_ext)] + new_ext z_out.writestr(new_name, z_in.read(entry.filename)) else: z_out.writestr(entry, z_in.read(entry.filename)) # 替换原Zip包 os.replace(tmp_zip, zip_path) # 使用示例:替换test.zip中的.pdg为.png rename_ext_in_zip("test.zip", ".pdg", ".png")
内容的提问来源于stack exchange,提问作者Schezuk
相关产品推荐
相关产品推荐

