如何在重定向时优雅地原地替换文件(PDF处理场景)
简化Ghostscript PDF重写的命令方式
已实现的操作
- 依赖安装:
- 通过
sudo dnf install -y ghostscript安装gs(Ghostscript) - 通过
uv tool install gdown安装gdown
- 通过
- 当前执行脚本:
y="$(cat<<EOF 13pLj7wS3CyX31YDTmz4j5Y2bMtX6HY7z EOF )" gdown "$y" pf="$(cat<<EOF Bando-Ing.-BIO-e-IFO-2024-ok31.pdf EOF )" td="$(cat<<EOF tp.pdf EOF )" touch "$td" gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=%stdout% -f "$pf" > "$td" cp "$td" "$pf" rm -rf "$td"
问题
无法直接执行 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=%stdout% -f "$pf" > "$pf"(直接覆盖原文件会触发读写冲突),希望找到更简洁的替代方法,避免当前临时文件迂回的操作。
可行替代方案
方案1:用mktemp自动生成安全临时文件
借助系统自带的mktemp生成唯一临时文件,完成处理后原子替换原文件,比手动指定临时文件名更安全:
y="13pLj7wS3CyX31YDTmz4j5Y2bMtX6HY7z" gdown "$y" pf="Bando-Ing.-BIO-e-IFO-2024-ok31.pdf" # 自动生成临时文件 temp_pdf=$(mktemp) # 直接将Ghostscript输出写入临时文件 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile="$temp_pdf" -f "$pf" # 原子替换原文件(保证操作原子性,避免中途中断损坏文件) mv "$temp_pdf" "$pf"
方案2:使用sponge工具(需额外安装)
sponge是moreutils包中的工具,会先读取所有输入内容,再打开目标文件写入,完美解决同一文件读写冲突问题:
# 先安装依赖工具 sudo dnf install -y moreutils y="13pLj7wS3CyX31YDTmz4j5Y2bMtX6HY7z" gdown "$y" pf="Bando-Ing.-BIO-e-IFO-2024-ok31.pdf" # 直接通过管道将输出传给sponge写入原文件 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=%stdout% -f "$pf" | sponge "$pf"
方案3:简化原脚本逻辑
如果不想改变核心流程,只是精简代码,可以去掉冗余的cat<<EOF和touch,用&&保证执行顺序:
y="13pLj7wS3CyX31YDTmz4j5Y2bMtX6HY7z" gdown "$y" pf="Bando-Ing.-BIO-e-IFO-2024-ok31.pdf" td="tp.pdf" # 生成临时文件后直接替换,省去touch和单独rm步骤 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=%stdout% -f "$pf" > "$td" && mv "$td" "$pf"
内容的提问来源于stack exchange,提问作者Signor Pizza




