【问题标题】:Splitting a PDF with Ghostscript使用 Ghostscript 分割 PDF
【发布时间】:2012-04-30 23:57:07
【问题描述】:

我尝试使用 Ghostscript 拆分多页 PDF,我在更多网站甚至ghostscript.com 上找到了相同的解决方案,即:

gs -sDEVICE=pdfwrite -dSAFER -o outname.%d.pdf input.pdf

但这似乎对我不起作用,因为它会生成一个文件,其中 所有页面,名称为 outname.1.pdf.

当我添加开始页面和结束页面时,它工作正常,但我 希望它在不知道这些参数的情况下工作。

在 gs-devel 存档中,我找到了一个解决方案: http://ghostscript.com/pipermail/gs-devel/2009-April/008310.html-- 但我想在没有pdf_info 的情况下这样做。

当我使用不同的设备时,例如pswrite,但相同 参数,它可以正常工作,生成尽可能多的 ps 文件,就像我的 input.pdf 包含。

使用pdfwrite时这正常吗?我是不是做错了什么?

【问题讨论】:

    标签: pdf-generation ghostscript


    【解决方案1】:

    我发现 Weimer 先生编写的这个脚本非常有用:

    #!/bin/sh
    #
    # pdfsplit [input.pdf] [first_page] [last_page] [output.pdf] 
    #
    # Example: pdfsplit big_file.pdf 10 20 pages_ten_to_twenty.pdf
    #
    # written by: Westley Weimer, Wed Mar 19 17:58:09 EDT 2008
    #
    # The trick: ghostscript (gs) will do PDF splitting for you, it's just not
    # obvious and the required defines are not listed in the manual page. 
    
    if [ $# -lt 4 ] 
    then
            echo "Usage: pdfsplit input.pdf first_page last_page output.pdf"
            exit 1
    fi
    gs -dNOPAUSE -dQUIET -dBATCH -sOutputFile="$4" -dFirstPage=$2 -dLastPage=$3 -sDEVICE=pdfwrite "$1"
    

    来源:http://www.cs.virginia.edu/~weimer/pdfsplit/pdfsplit

    将其保存为pdfsplit.sh,看看奇迹发生了。

    PDFSAM 也可以完成这项工作。适用于 Windows 和 Mac。

    【讨论】:

    • 太棒了。我没有 pdftk 和 psselect 会失去一些 pdf 质量,但不是这个。
    • 感谢您提供指向 -dFirstPage=... 和 -dLastPage=... 参数的指针!
    【解决方案2】:

    您看到的是“正常”行为:Ghostscript 的pdfwrite 输出设备的当前版本不支持此功能。 Use.htm 中也记录了这一点(诚然,有些模糊):

    “请注意,并非所有设备都支持每个文件一页的功能......”

    我似乎记得一位 Ghostscript 开发人员在 IRC 上提到,他们可能在未来的某个版本中将此功能添加到 pdfwrite,但这似乎需要一些主要的代码重写,这就是为什么他们还没做...


    更新: 正如 Gordon 的评论已经暗示的那样,截至 version 9.06(2012 年 7 月 31 日发布),Ghostscript 现在支持问题中引用的命令行也适用于 pdfwrite。 (Gordon 一定是在 9.05 中发现了对此的非官方支持,或者他从尚未标记为 9.06 的预发布源编译了自己的可执行文件。

    【讨论】:

    • 是的,我读过这一行,但我的短语“正常行为”想要表示“pdfwrite 是可能不支持此功能的人之一吗?”你记住这个 IRC 对我来说没问题,谢谢。
    • 对于在搜索中找到此答案的人:从 9.05 开始,使用 OP 的命令,每个文件一页对我有效。
    • @Gordon:支持-o out_%d.pdf 语法(将多页 PDF 拆分为每页的单个文件)在 9.06 中成为正式版本。我已经在其他答案中暗示了这一点(例如 Split multi page PDF file into single pages)。我忘了更新这个答案。感谢您的提示。
    【解决方案3】:
     #!/bin/bash
    #where $1 is the input filename
    
    ournum=`gs -q -dNODISPLAY -c "("$1") (r) file runpdfbegin pdfpagecount = quit" 2>/dev/null`
    echo "Processing $ournum pages"
    counter=1
    while [ $counter -le $ournum ] ; do
        newname=`echo $1 | sed -e s/\.pdf//g`
        reallynewname=$newname-$counter.pdf
        counterplus=$((counter+1))
        # make the individual pdf page
        yes | gs -dBATCH -sOutputFile="$reallynewname" -dFirstPage=$counter -dLastPage=$counter -sDEVICE=pdfwrite "$1" >& /dev/null
        counter=$counterplus
    done
    

    【讨论】:

      【解决方案4】:

      假设您安装了 Ghostscript,以下是 Windows 命令提示符的脚本(也可用于拖放):

      @echo off
      chcp 65001
      setlocal enabledelayedexpansion
      
      rem Customize or remove this line if you already have Ghostscript folders in your system PATH
      set path=C:\Program Files\gs\gs9.22\lib;C:\Program Files\gs\gs9.22\bin;%path%
      
      :start
      
      echo Splitting "%~n1%~x1" into standalone single pages...
      cd %~d1%~p1
      rem getting number of pages of PDF with GhostScript
      for /f "usebackq delims=" %%a in (`gswin64c -q -dNODISPLAY -c "(%~n1%~x1) (r) file runpdfbegin pdfpagecount = quit"`) do set "numpages=%%a"
      
      for /L %%n in (1,1,%numpages%) do (
      echo Extracting page %%n of %numpages%...
      set "x=00%%n"
      set "x=!x:~-3!"
      gswin64c.exe -dNumRenderingThreads=2 -dBATCH -dNOPAUSE -dQUIET -dFirstPage=%%n -dLastPage=%%n -sDEVICE=pdfwrite -sOutputFile="%~d1%~p1%~n1-!x!.pdf" "%1"
      )
      
      shift
      if NOT x%1==x goto start
      
      pause
      

      将此脚本命名为split PDF.bat 之类的名称并将其放在您的桌面上。将一个(甚至更多)多页 PDF 拖放到其上,它将为 PDF 的每一页创建一个独立的 PDF 文件,并在名称后附加后缀 -001-002 等以区分页面。

      如果您的系统 PATH 环境变量中已有 Ghostscript 文件夹,您可能需要自定义(使用相关的 Ghostscript 版本)或删除 set path=... 行。

      它适用于带有 Ghostscript 9.22 的 Windows 10。请参阅 cmets 以使其与 Ghostscript 9.50+ 一起使用。

      享受吧。

      【讨论】:

      • +1 用于获取 GS 的页数,干得好!如果有人想在 linux/macOS 上获取页数,请使用 gs -q -dNODISPLAY -c "(../escaped\ file \name.pdf) (r) file runpdfbegin pdfpagecount = quit"
      • 非常有帮助。可以与 GS 9.22 一起使用,但在某种程度上与(至少)9.50 和 9.52 不兼容。有人知道如何解决这个问题吗?
      • @user18258 我不知道如何解决这个问题,但无论如何我发现使用另一个命令行工具在 Windows 上分割 PDF 文件更方便,sedja 控制台。这是一个拖放批次:codepile.net/pile/6lWv3wzY
      • @mmj 感谢基于sedja 的代码!我将 GhostScript 用于许多“shell:sendto”任务,并且仍然对 9.52 兼容的解决方案感兴趣 - 尽管我知道您不会提供它。我在上面的基于 GS 的代码中发现了一个小错误(我仍在使用 GS 版本 9.27!):我认为 gswin64c.exe ... "%1" 应该是 gswin64c.exe ... %1,否则当路径包含空格时会出现问题。
      • @tstone-1 似乎对于 Ghostscript 9.50+,您必须添加 -dNOSAFER 选项(连同 -dNODISPLAY)。见:stackoverflow.com/q/40156190
      【解决方案5】:

      这是一个简单的 python 脚本:

      #!/usr/bin/python3
      
      import os
      
      number_of_pages = 68
      input_pdf = "abstracts_rev09.pdf"
      
      for i in range(1, number_of_pages +1):
          os.system("gs -q -dBATCH -dNOPAUSE -sOutputFile=page{page:04d}.pdf"
                    " -dFirstPage={page} -dLastPage={page}"
                    " -sDEVICE=pdfwrite {input_pdf}"
                    .format(page=i, input_pdf=input_pdf))
      

      【讨论】:

        【解决方案6】:

        更新的答案仅依赖于 pdftk.exe,而不调用 Ghostscript

        用户@mmj 提供的答案过去对我来说很好用,但不知何故在 GS 版本 9.20 和 9.50 之间的某个地方停止了工作。我也知道@Adobe 提供的解决方案。但是,我喜欢通过选择一个或多个文件并右键单击 → 发送到,从 Windows (10) 资源管理器中完成重复性任务。这是一个 Python 脚本(与 3.8 兼容),它使用 pdftk.exe(用 2.02 测试)来计算总页数并将全部提取到单个文件中。它应该接受多个 PDF 作为输入。确保 PATH 中有 Python 和 pdftk.exe

        将此命名为extract-pdf-pages-py.cmd 并将其命名为shell:sendto

        python %APPDATA%\Microsoft\Windows\SendTo\extract-pdf-pages-py.py %*
        

        把下面的extract-pdf-pages-py.py放到同一个文件夹里:

        #!/usr/bin/python3
        # put as extract-pdf-pages-py.py to shell:sendto
        
        import os
        import subprocess
        import re
        import sys
        import mimetypes
        
        
        def is_tool(name):
            from shutil import which
            return which(name) is not None
        
        
        if not is_tool('pdftk'):
            input('pdftk.exe not within PATH. Aborting...')
            raise SystemExit("pdftk.exe not within PATH.")
        
        sys.argv.pop(0)
        
        for j in range(len(sys.argv)):
            input_pdf = sys.argv[j]
        
            if 'application/pdf' not in mimetypes.guess_type(input_pdf):
                input(f"File {input_pdf} is not a PDF. Skipping...")
                continue
        
            savefile = input_pdf.rstrip('.pdf')
        
            numpages = subprocess.Popen(f"pdftk \"{input_pdf}\" dump_data", shell=True, stdout=subprocess.PIPE)
            output1 = str(numpages.communicate()[0])
            output2 = re.search("NumberOfPages: ([0-9]*)", output1)
            number_of_pages = int(output2.group(1))
        
            for i in range(1, number_of_pages + 1):
                os.system(f"pdftk \"{input_pdf}\" cat {i} output \"{savefile}\"{i:04d}.pdf")
        

        我使用了来自this answer(@Adobe 编写的脚本)和that one (is_tool) 的代码。

        【讨论】:

          【解决方案7】:

          gs 只接受升序页面。 为了从源代码中改组(即第 7、第 8、第 5)页,我为 ~/.bashrc 创建了函数:

          function expdf
          {
          local str=""
          local arr=($(echo $1 | tr "," "\n"))
          #          splitting
          for i in "${arr[@]}";do
            gs -dBATCH -sDEVICE=pdfwrite -sPageList=$i -dNOPAUSE -sOutputFile=$i.tmp $2
          #          reordering for combining
            str="$str $i.tmp"
          done
          #          combining to combine.pdf
          gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=combine.pdf -dBATCH $str
          #          removing temporary files
          for i in "${arr[@]}";do rm $i.tmp;done
          }
          

          使用示例:expdf 7-8,5 source.pdf

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-09-05
            • 2011-11-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-03-07
            • 2016-02-16
            相关资源
            最近更新 更多