You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过Shell脚本调用ImageMagick时出现无限循环问题求助

LuaLaTeX中通过ShellEscape调用ImageMagick的变量传递问题

问题现象

通过LuaLaTeX的\ShellEscape调用ImageMagick做PDF后处理时,用变量传递文件名会导致进程停滞:执行到convert命令时无报错、CPU无占用,但任务永远无法完成;直接在命令中写死文件名则一切正常。

复现命令

控制台执行的编译命令:

rm -rf output-Pi/ && lualatex --shell-escape Pi.tex

代码对比

异常调用(变量传递)

page_array='\"output-Pi/te@mp.com/Main Fu - Pi Lo.pdf[0]\"' &&
convert $(echo $page_array) merge.pdf

正常调用(直接写死文件名)

convert \"output-Pi/te@mp.com/Main Fu - Pi Lo.pdf[0]\" merge.pdf

复杂场景背景

由于需要经过TeX解释器→Lua→Shell三层解释器转义,特殊字符处理极其繁琐,相关Lua代码片段如下:

tex.sprint("\\ShellEscape{%
    main_dir=\"output-\\jobname\" &&
    email_dir=\"${main_dir}/\", ii[1]:gsub(\",\", \"\"), \"\" &&
    pdf_file_name=\"${email_dir}/Main Fu - Pi Lo\" &&
    mkdir -p $main_dir &&
    mkdir -p $email_dir &&
    lualatex --jobname=\"${pdf_file_name}\" \"\\gdef\\string\\conditionmacro{", t[i], "}\\string\\input\\space\\jobname\" && 
    pdf_file_page=$(identify \"${pdf_file_name}.pdf\" 2>/dev/null | wc -l | tr -d ' ') &&
    page=0 &&
    quote='\"' &&
    while [ $page -lt $pdf_file_page ] ; do page=$(($page + 1)) && page2=$(($page-1)) && echo \"${page2} - ${pdf_file_name}\" &&
    pdf_file_name2=$(echo $pdf_file_name | sed 's/ /\\\\\\ /g') &&
    page_array=\"${page_array}${quote}${pdf_file_name}.pdf[${page2}]\" && page_array=$(echo \"${page_array}${quote} \") ; done &&
    echo \"------------------------------------\" &&
    echo $page_array &&
    echo $SHELL &&
    page_array='\"output-Pi/te@mp.com/Main Fu - Pi Lo.pdf[0]\"' &&
    echo \"convert -density 300 $(echo $page_array) -background  white -density 300 merge.pdf\" &&
    convert $(echo $page_array) merge.pdf &&
    echo \"DONE\"
    }")

解决办法

  • 避免多余的变量展开:Shell中直接使用变量即可保留空格和引号,无需用$(echo $page_array)处理,修改异常调用为:

    page_array='"output-Pi/te@mp.com/Main Fu - Pi Lo.pdf[0]"' &&
    convert $page_array merge.pdf
    
  • 改用Shell数组存储路径:多页面场景下,用数组替代字符串拼接,彻底规避空格、特殊字符的转义问题:

    # 初始化数组
    page_array=()
    # 循环添加页面路径
    page_array+=("${pdf_file_name}.pdf[${page2}]")
    # 调用convert时直接传递数组
    convert "${page_array[@]}" merge.pdf
    
  • 简化三层转义逻辑:在Lua中编写辅助函数统一转义Shell特殊字符,减少手动嵌套转义的出错概率:

    function shell_escape(s)
        return "'" .. s:gsub("'", "'\\''") .. "'"
    end
    

    生成Shell命令时用该函数处理文件名:

    local escaped_pdf = shell_escape(pdf_file_name .. ".pdf[" .. page2 .. "]")
    tex.sprint("page_array+=(" .. escaped_pdf .. ")")
    
  • 开启调试模式定位问题:在Shell命令开头添加set -x,可以查看实际执行的命令内容,快速定位转义错误:

    tex.sprint("\\ShellEscape{%
        set -x
        # 其余命令...
    }")
    

内容的提问来源于stack exchange,提问作者Nikulok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 12:31:04