Як я можу об'єднати PDF-файли, щоб кожен файл починався з непарного номера сторінки?


11

Мені потрібно об'єднати декілька замаринованих pdfs, і я хочу, щоб усі вхідні pdfs починалися на непарній сторінці у вихідному PDF.

Приклад: A.pdfмає 3 сторінки, B.pdfмає 4 сторінки. Я не хочу, щоб мій вихід мав 7 сторінок. Мені хочеться - це 8-сторінковий pdf, в якому сторінки 1-3 A.pdf, сторінки 4 порожні, а сторінки 5-8 - від B.pdf. Як я можу це зробити?

Я знаю про pdftk, але такого варіанту на сторінці man не знайшов.

Відповіді:


6

Бібліотека PyPdf полегшує подібні речі, якщо ви готові написати трохи Python. Збережіть код нижче у скрипті під назвою pdf-cat-even(або як завгодно), зробіть його виконуваним ( chmod +x pdf-cat-even) та запустіть його як фільтр ( ./pdf-cat-even a.pdf b.pdf >concatenated.pdf). Для методу вам потрібен pyPdf ≥1.13 addBlankPage.

#!/usr/bin/env python
import copy, sys
from pyPdf import PdfFileWriter, PdfFileReader
output = PdfFileWriter()
output_page_number = 0
alignment = 2           # to align on even pages
for filename in sys.argv[1:]:
    # This code is executed for every file in turn
    input = PdfFileReader(open(filename))
    for p in [input.getPage(i) for i in range(0,input.getNumPages())]:
        # This code is executed for every input page in turn
        output.addPage(p)
        output_page_number += 1
    while output_page_number % alignment != 0:
        output.addBlankPage()
        output_page_number += 1
output.write(sys.stdout)

Дякую, це працювало для мене! Оскільки я вважаю за краще читати імена pdfs з файлу, я трохи змінив ваш код і розмістив його як окрему відповідь .
Jan Warchoł

@JanekWarchol Якщо імена файлів не містять оболонки спеціальні символи , такі як прогалини:./pdf-cat-even $(cat list-of-file-names.txt) >concatenated.pdf
Жиля SO- перестати бути злом "

На жаль, вони містять пробіли. Але все-таки спасибі - я не розумів, що це можна зробити так.
Jan Warchoł

@JanekWarchol Тоді ви можете використовувати<list-of-file-names.txt tr '\n' '\0' | xargs -0 ./pdf-cat-even >concatenated.pdf
"SO- перестань бути злим"

3

Перший крок - створити файл PDF з порожньою сторінкою. Це можна легко зробити за допомогою багатьох програм (LibreOffice / OpenOffice, inkscape, (La) TeX, scribus тощо)

Тоді просто включіть цю порожню сторінку там, де потрібно:

pdftk A.pdf empty_page.pdf B.pdf output result.pdf 

Якщо ви хочете зробити це автоматично за допомогою сценарію, ви можете використовувати, наприклад, pdftk file.pdf dump_data | grep NumberOfPages | egrep -o '[0-9]*'витягнути кількість сторінок.


Це здається, що трохи зламати. Хоча якщо це працює, я думаю, він працює.
Сем Білий

Такий підхід для мене майже не працював: я написав сценарій, який створив список pdfs з додаванням epmtyPage.pdf, де потрібно, але я не зміг отримати pdftk, щоб правильно проаналізувати цей список, якщо в назви файлів були пробіли. Я спробував змінити значення IFS, використовуючи лапки, але безрезультатно - можливо, це вина pdftk. У будь-якому випадку, відповідь за допомогою pypdf працював для мене.
Jan Warchoł

@JanekWarchol Яку версію pdftk ви використовували? Принаймні, pdftk 1,44 і новіші, здається, підтримують пробіли у назви файлів.
jofel

@jofel pdftk --versionповертає pdftk 1,44. Я пам’ятаю, що мої більш зграбні друзі витрачали щонайменше 15 хвилин на те, щоб розібратися з цією справою, і здалися.
Jan Warchoł

1

Відповідь Гілла працювала на мене, але оскільки мені доводиться об’єднувати багато файлів, це зручніше, якщо я можу прочитати їхні імена з текстового файлу. Я трохи змінив код Жиля, щоб зробити саме це, можливо, це допоможе комусь іншому:

#!/usr/bin/env python

# requires PyPdf library, version 1.13 or above -
# its homepage is http://pybrary.net/pyPdf/
# running: ./this-script-name file-with-pdf-list > output.pdf

import copy, sys
from pyPdf import PdfFileWriter, PdfFileReader
output = PdfFileWriter()
output_page_number = 0

# every new file should start on (n*alignment + 1)th page
# (with value 2 this means starting always on an odd page)
alignment = 2

listoffiles = open(sys.argv[1]).read().splitlines()
for filename in listoffiles:
    # This code is executed for every file in turn
    input = PdfFileReader(open(filename))
    for p in [input.getPage(i) for i in range(0,input.getNumPages())]:
        # This code is executed for every input page in turn
        output.addPage(p)
        output_page_number += 1
    while output_page_number % alignment != 0:
        output.addBlankPage()
        output_page_number += 1
output.write(sys.stdout)

1

Ви також можете використовувати LaTeX для цього (хоча я знаю, що це, мабуть, не те, що ви хочете). Щось таке, що має працювати:

\documentclass{book}

\usepackage{pdfpages}

\begin{document}

\includepdf[pages=-]{A}
\cleardoublepage % Make sure we clear to an odd page
\includepdf[pages=-]{B} % This inserts all pages. Or you can specify specific pages, a range, or `{}` for a blank page

\end{document}

Зауважте, що \cleardoublepageвставляється лише порожня сторінка з класами, які створені для двостороннього друку (наприклад, книга)

Додаткові параметри та інформацію pdfpagesможна знайти на CTAN .


2
Щоб автоматично включати всі сторінки, ви можете використовувати \includepdf[pages=-]{...}.
jofel

@jofel Спасибі, вирішив питання. Я думаю, що це також за замовчуванням для всіх сторінок, я просто помістив його там, щоб показати, що можна вибрати певні сторінки.
Сем Віт

@jofel Також \cleardoublepageпорожню сторінку вставляє лише тоді, коли ви використовуєте клас, виготовлений для двостороннього друку. Я використовував статтю, яка не працює; Я виправив це і оновив питання, щоб це відобразити.
Сем Білий

\includepdfза замовчуванням включає лише першу сторінку (не всі сторінки). \documentclass[twoside]{article}працює також.
jofel

З того, що я бачу, мені доведеться чітко писати всі файли, які повинні бути включені, так що це недостатньо добре для мене. Але все-таки спасибі
Jan Warchoł

0

Ось код з PyPDF2 та python3

#!/usr/bin/env python


# requires PyPdf2 library, version 1.26 or above -
# its homepage is https://pythonhosted.org/PyPDF2/index.html
# running: ./this-script-name output.pdf file-with-pdf-list

import copy, sys
from PyPDF2 import PdfFileWriter, PdfFileReader
output = PdfFileWriter()
output_page_number = 0

# every new file should start on (n*alignment + 1)th page
# (with value 2 this means starting always on an odd page)
alignment = 2

for filename in sys.argv[2:]:
    # This code is executed for every file in turn
    input = PdfFileReader(open(filename, "rb"))
    output.appendPagesFromReader(input)
    output_page_number += input.getNumPages()

    while output_page_number % alignment != 0:
        output.addBlankPage()
        output_page_number += 1

output.write(open(sys.argv[1], "wb"))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.