unix 我如何合并PDF文件(或PS,如果不可能),使每个文件将开始在一个奇数页?

mftmpeh8  于 2023-02-12  发布在  Unix
关注(0)|答案(9)|浏览(171)

我在UNIX系统上工作,我想把几千个PDF文件合并成一个文件来打印,我不知道它们有多少页。
我想双面打印,这样两个文件就不会在同一页上了。
因此,它我的合并文件要对齐,使每个文件将开始在奇数页和一个空白页将被添加,如果下一个地方写的是一个偶数页。

gv8xihay

gv8xihay1#

下面是我使用的解决方案(它基于@Dingo的基本原理,但使用了一种更简单的PDF操作方法):
1.创建包含一个空白页的PDF文件
首先,创建一个PDF文件,其中有一个空白页(在我的例子中,它位于/path/to/blank.pdf)。

touch blank.ps && ps2pdf blank.ps blank.pdf

1.运行Bash脚本
然后,从包含所有PDF文件的目录中,运行一个小脚本,将blank.pdf文件附加到每个具有奇数页码的PDF文件:

#!/bin/bash

for f in *.pdf; do
  let npages=$(pdfinfo "$f"|grep 'Pages:'|awk '{print $2}')
  let modulo="($npages %2)"
  if [ $modulo -eq 1 ]; then
    pdftk "$f" "/path/to/blank.pdf" output "aligned_$f"
    # or
    # pdfunite "$f" "/path/to/blank.pdf" "aligned_$f"
  else
    cp "$f" "aligned_$f"
  fi
done

1.合并结果
现在,所有以aligned_为前缀的文件都有偶数页码,我可以使用

pdftk aligned_*.pdf output result.pdf
# or
pdfunite aligned_*.pdf result.pdf

工具信息:

  • ps2pdf包含在大多数Linux发行版的**ghostscript软件包**中
  • pdfinfopdfunite来自Poppler PDF rendering library(通常软件包名称为**poppler-utilspoppler_utils**)
  • pdftk通常是它自己的软件包,即**pdftk软件包**
klr1opcd

klr1opcd2#

如果你从另一个Angular 来看这个问题,你的问题会更容易解决
为了获得在打印中,* 第二 * PDF文件的第1页将不附在 * 相同 * 纸张上的 * 第一 * PDF文件的最后一页上,并且更一般地,后续PDF文件的第一页将不与在先PDF文件的最后一页打印在相同纸张的背面
你需要到执行一个选择性的添加一个空白页仅仅到pdf文件有和奇数页
我编写了一个名为abbblankifneeded的简单脚本,您可以将其放入文件中,然后将其复制到**/usr/bin/usr/local/bin**中
然后用以下语法在存放pdf的文件夹中调用
for f in *.pdf; do addblankifneeded $f; done
此脚本在具有奇数页的pdf文件末尾添加一个空白页,跳过已经具有偶数页的pdf文件,然后将所有pdf合并为一个

  • 要求:*pdftkpdfinfo
    注意:根据您的bash环境,您可能需要在脚本的第一行将sh interpreter替换为bash interpreter
#!/bin/sh
#script to add automatically blank page at the end of a pdf documents, if count of their pages is a not a module of 2 and then to join all pdfs into one
#
#  made by Dingo
#
# dokupuppylinux.co.cc
#
#http://pastebin.com/u/dingodog (my pastebin toolbox for pdf scripts)
#
filename=$1
altxlarg="`pdfinfo -box $filename| grep MediaBox | cut -d : -f2 | awk '{print $3 FS $4}'`"
echo "%PDF-1.4
%µí®û
3 0 obj
<<
/Length 0
>>
stream
endstream
endobj
4 0 obj
<<
/ProcSet [/PDF ]
/ExtGState <<
/GS1 1 0 R
>>
>>
endobj
5 0 obj
<<
/Type /Halftone
/HalftoneType 1
/HalftoneName (Default)
/Frequency 60
/Angle 45
/SpotFunction /Round
>>
endobj
1 0 obj
<<
/Type /ExtGState
/SA false
/OP false
/HT /Default
>>
endobj
2 0 obj
<<
/Type /Page
/Parent 7 0 R
/Resources 4 0 R
/Contents 3 0 R
>>
endobj
7 0 obj
<<
/Type /Pages
/Kids [2 0 R ]
/Count 1
/MediaBox [0 0 595 841]
>>
endobj
6 0 obj
<<
/Type /Catalog
/Pages 7 0 R
>>
endobj
8 0 obj
<<
/CreationDate (D:20110915222508)
/Producer (libgnomeprint Ver: 2.12.1)
>>
endobj
xref
0 9
0000000000 65535 f
0000000278 00000 n
0000000357 00000 n
0000000017 00000 n
0000000072 00000 n
0000000146 00000 n
0000000535 00000 n
0000000445 00000 n
0000000590 00000 n
trailer
<<
/Size 9
/Root 6 0 R
/Info 8 0 R
>>
startxref
688
%%EOF" | sed -e "s/595 841/$altxlarg/g">blank.pdf
pdftk blank.pdf output fixed.pdf
mv fixed.pdf blank.pdf
pages="`pdftk $filename dump_data | grep NumberOfPages | cut -d : -f2`"
if [ $(( $pages % 2 )) -eq 0 ]
    then echo "$filename has already a multiple of 2 pages ($pages ). Script will be skipped for this file" >>report.txt
    else
pdftk A=$filename B=blank.pdf cat A B output blankadded.pdf
mv blankadded.pdf $filename
pdffiles=`ls *.pdf | grep -v -e blank.pdf -e joinedtogether.pdf| xargs -n 1`;  pdftk $pdffiles cat output joinedtogether.pdf
fi
exit 0
vybvopom

vybvopom3#

您可以使用PDFsam

  • 免费的
  • 在Microsoft Windows、Mac OS X和Linux上运行
  • 提供便携版本(至少在Windows上)
  • 如果文档的页数为奇数,则可以在每个合并文档后添加一个空白页

ubof19bj

ubof19bj4#

免责声明:我是我在这里提到的工具的作者。

sejda-控制台

这是一个免费的开源命令行界面,用于执行pdf操作,如合并或拆分。merge命令有一个选项,声明如下:
[--添加空白]:如果页数为奇数,则在每个合并文档后添加一个空白页(可选)
既然你只需要打印pdf文件,我想你并不关心文件合并的顺序。下面是你可以使用的命令:
sejda-console merge -d /path/to/pdfs_to_merge -o /outputpath/merged_file.pdf --addBlanks
可从官方网站sejda.org下载。

**一个

这是一个由Sejda支持的Web应用程序,具有上述相同的功能,但通过Web界面。您需要上传文件,因此,根据输入集的大小,它可能不是适合您的解决方案。
如果您选择merge命令并上传您的pdf文档,您将必须标记复选框Add blank page if odd page number以获得所需的行为。

qlckcl4x

qlckcl4x5#

这是一个使用pdftk的最流行的解决方案的PowerShell版本。我是为Windows做的,但是你可以为其他平台使用PowerShell核心。

# install pdftk server if on windows
# https://www.pdflabs.com/tools/pdftk-server/

$blank_pdf_path = ".\blank.pdf"
$input_folder = ".\input\"
$aligned_folder = ".\aligned\"
$final_output_path = ".\result.pdf"

foreach($file in (Get-ChildItem $input_folder -Filter *.pdf))
{
    # easy but might break if pdfinfo output changes
    # takes 7th line with the "Page: 2" and matches only numbers
    (pdfinfo $file.FullName)[7] -match "(\d+)" | Out-Null

    $npages = $Matches[1]
    $modulo = $npages % 2

    if($modulo -eq 1)
    {
        $output_path = Join-Path $aligned_folder $file.Name
        pdftk $file.FullName $blank_pdf_path output $output_path
    }
    else
    {
        Copy-Item $file.FullName -Destination $aligned_folder
    }
}

$aligned_pdfs = Join-Path $aligned_folder "*.pdf"
pdftk $aligned_pdfs output $final_output_path
mbjcgjjk

mbjcgjjk6#

准备
1.安装Python并确保您有pyPDF包。
1.在/path/to/blank.pdf中创建一个带有一个空格的PDF文件(我已经创建了blank pdf pages here)。
1.将此文件保存为pdfmerge.py,保存在$PATH的任意目录中。(我不是Windows用户。这在Linux下是直接的。如果您遇到错误/如果它工作,请让我知道。)
1.使pdfmerge.py可执行
每当你需要它
运行uniprint.py,找到仅包含要合并的PDF文件的目录。
pdfmerge.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from argparse import ArgumentParser
from glob import glob
from pyPdf import PdfFileReader, PdfFileWriter

def merge(path, blank_filename, output_filename):
    blank = PdfFileReader(file(blank_filename, "rb"))
    output = PdfFileWriter()

    for pdffile in glob('*.pdf'):
        if pdffile == output_filename:
            continue
        print("Parse '%s'" % pdffile)
        document = PdfFileReader(open(pdffile, 'rb'))
        for i in range(document.getNumPages()):
            output.addPage(document.getPage(i))

        if document.getNumPages() % 2 == 1:
            output.addPage(blank.getPage(0))
            print("Add blank page to '%s' (had %i pages)" % (pdffile, document.getNumPages()))
    print("Start writing '%s'" % output_filename)
    output_stream = file(output_filename, "wb")
    output.write(output_stream)
    output_stream.close()

if __name__ == "__main__":
    parser = ArgumentParser()

    # Add more options if you like
    parser.add_argument("-o", "--output", dest="output_filename", default="merged.pdf",
                      help="write merged PDF to FILE", metavar="FILE")
    parser.add_argument("-b", "--blank", dest="blank_filename", default="blank.pdf",
                      help="path to blank PDF file", metavar="FILE")
    parser.add_argument("-p", "--path", dest="path", default=".",
                      help="path of source PDF files")

    args = parser.parse_args()
    merge(args.path, args.blank_filename, args.output_filename)

测试

如果这在Windows和Mac上有效,请发表评论。
如果它不起作用/它可以改进,请总是留下评论。
它在Linux上工作。将3个PDF文件连接成一个200页的PDF文件只花了不到一秒钟。

clj7thdc

clj7thdc7#

Martin有一个很好的开始,我更新到了PyPdf2,并做了一些调整,比如按文件名对输出进行排序。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from argparse import ArgumentParser
from glob import glob
from PyPDF2 import PdfFileReader, PdfFileWriter
import os.path
def merge(pdfpath, blank_filename, output_filename):

    with open(blank_filename, "rb") as f:
        blank = PdfFileReader(f)
        output = PdfFileWriter()

        filelist = sorted(glob(os.path.join(pdfpath,'*.pdf')))

        for pdffile in filelist:
            if pdffile == output_filename:
                continue
            print("Parse '%s'" % pdffile)

            document = PdfFileReader(open(pdffile, 'rb'))

            for i in range(document.getNumPages()):
                output.addPage(document.getPage(i))

            if document.getNumPages() % 2 == 1:
                output.addPage(blank.getPage(0))

            print("Add blank page to '%s' (had %i pages)" % (pdffile, document.getNumPages()))

        print("Start writing '%s'" % output_filename)
        with open(output_filename, "wb") as output_stream:
            output.write(output_stream)

if __name__ == "__main__":
    parser = ArgumentParser()

    # Add more options if you like
    parser.add_argument("-o", "--output", dest="output_filename", default="merged.pdf",
                      help="write merged PDF to FILE", metavar="FILE")
    parser.add_argument("-b", "--blank", dest="blank_filename", default="blank.pdf",
                      help="path to blank PDF file", metavar="FILE")
    parser.add_argument("-p", "--path", dest="path", default=".",
                      help="path of source PDF files")

    args = parser.parse_args()
    merge(args.path, args.blank_filename, args.output_filename)
`
u91tlkcl

u91tlkcl8#

@Chris Lercher在https://stackoverflow.com/a/12761103/1369181中的代码不太适合我。我不知道这是否是因为我正在处理Cygwin/mintty。另外,我必须使用qpdf而不是pdftk。下面是适合我的代码:

#!/bin/bash

for f in *.pdf; do
  npages=$(pdfinfo "$f"|grep 'Pages:'|sed 's/[^0-9]*//g')
  modulo=$(($npages %2))
  if [ $modulo -eq 1 ]; then
    qpdf --empty --pages "$f" "path/to/blank.pdf" -- "aligned_$f"
  else
    cp "$f" "aligned_$f"
  fi
done

现在,所有的“aligned_”文件都有偶数页码,我可以使用qpdf(多亏了https://stackoverflow.com/a/51080927)将它们连接起来:

qpdf --verbose --empty --pages aligned_* -- all.pdf

这里是我用来创建空白页的https://unix.stackexchange.com/a/272878中的有用代码:

echo "" | ps2pdf -sPAPERSIZE=a4 - blank.pdf
yrefmtwq

yrefmtwq9#

这一个为我工作。在macos上使用pdfcpu。可以这样安装:

brew install pdfcpu

并对https://stackoverflow.com/a/12761103/1369181的代码进行了轻微调整

#!/bin/bash
mkdir aligned
for f in *.pdf; do
  let npages=$(pdfcpu info "$f"|grep 'Page count:'|awk '{print $3}')
  let modulo="($npages %2)"
  if [ $modulo -eq 1 ]; then
    pdfcpu page insert -pages l -mode after "$f" "aligned/$f"
  else
    cp "$f" "aligned/$f"
  fi
done
pdfcpu merge merged-aligned.pdf aligned/*.pdf
rm -rf aligned

注意!它在当前目录中创建和删除“对齐”目录。所以请随时改进它,使其安全使用。

相关问题