使用Ghostscript拆分PDF

时间:2012-04-19 12:57:06

标签: pdf-generation ghostscript

我尝试用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时这是正常的吗?我做错了吗?

6 个答案:

答案 0 :(得分:19)

我觉得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
yes | gs -dBATCH -sOutputFile="$4" -dFirstPage=$2 -dLastPage=$3 -sDEVICE=pdfwrite "$1" >& /dev/null

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

将其另存为pdfsplit.sh,看看神奇的事情发生了。

PDFSAM也可以胜任这项工作。适用于Windows和Mac。

答案 1 :(得分:10)

您看到的是“正常”行为:当前版本的Ghostscript的pdfwrite输出设备不支持此功能。在Use.htm

中也记录了这一点(不可否认,模糊地)
  

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

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


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

答案 2 :(得分:5)

 #!/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

答案 3 :(得分:3)

以下是Windows命令提示符的脚本(也可用于拖放操作),前提是您已安装Ghostscript:

@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下对我有效。

享受。

答案 4 :(得分:1)

这是一个简单的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))

答案 5 :(得分:0)

仅依靠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(@ Adob​​e的脚本)和that oneis_tool)中的代码。