Вопрос или проблема
Существует множество ресурсов в интернете, объясняющих, как можно разделить PDF-файл на множество файлов, по одной странице в каждом.
Но как можно разбить их на части по, скажем, пять страниц каждая? Я изучил стандартные инструменты такие как pdftk
, но не нашел подходящей опции.
pdftk
может эффективно извлекать фиксированный набор страниц. С небольшим дополнительным скриптингом, это делает то, что мне нужно:
number=$(pdfinfo -- "$file" 2> /dev/null | awk '$1 == "Pages:" {print $2}')
count=$((number / pagesper))
filename=${file%.pdf}
counter=0
while [ "$count" -gt "$counter" ]; do
start=$((counter*pagesper + 1));
end=$((start + pagesper - 1));
counterstring=$(printf %04d "$counter")
pdftk "$file" cat "${start}-${end}" output "${filename}_${counterstring}.pdf"
counter=$((counter + 1))
done
Это предполагает, что у вас есть количество страниц в каждом отрезке в $pagesper
и имя исходного PDF-файла в $file
.
Если у вас установлен acroread
, вы также можете использовать
acroread -size a4 -start "$start" -end "$end" -pairs "$file" "${filename}_${counterstring}.ps"
acroread
также предлагает опцию -toPostScript
, которая может быть полезной.
Также смотрите pdfseparate
и pdfunite
из poppler-utils
. pdfseparate
разбивает файл на файлы по одной странице, что упрощает их последующую сборку вручную или (полу)автоматически с помощью pdfunite
.
Как, например, с помощью zsh:
autoload zargs
reunite() pdfunite "$@" file-$1-$argv[-1].pdf
pdfseparate file.pdf p%d
zargs -n 5 p<->(n) -- reunite
rm -f p<->
разделит file.pdf
на file-p1-p5.pdf
, file-p6-p10.pdf
…
Я нахожу Python с библиотекой PyPdf удобным для задач, которые pdftk не выполняет удобно (или вообще).
PyPDF претерпел несовместимые изменения за эти годы. Вот версия, которая работает с Python 3 и PyPDF2 2.12. Возможно, потребуется корректировка для других версий.
#!/usr/bin/env python3
import sys
from PyPDF2 import PdfFileWriter, PdfFileReader
# Разбор командной строки
if len(sys.argv) < 2 or sys.argv[1][-4:] != '.pdf':
sys.stderr.write('Использование: ' + sys.argv[0] + ''' FILE.pdf N
Разделите FILE.pdf на части по N страниц каждая.
''')
exit(3)
pages_per_file = int(sys.argv[2])
base_name = sys.argv[1][:-4] + '-'
input_pdf = PdfFileReader(open(sys.argv[1], 'rb'))
output_pdf = PdfFileWriter()
num_pages = input_pdf.getNumPages()
for i in range(num_pages):
output_pdf.addPage(input_pdf.getPage(i))
if (i + 1) % pages_per_file == 0 or i + 1 == num_pages:
output_file = open(base_name + str(i // pages_per_file + 1) + '.pdf', "wb")
output_pdf.write(output_file)
output_file.close()
output_pdf = PdfFileWriter()
Решение, предложенное Рафаэлем, имеет недостаток: если у вас нечетное количество страниц, последние просто игнорируются. Вот улучшенное решение, которое работает также с нечетным количеством страниц.
Опять же, предполагается, что у вас есть количество страниц в каждом отрезке в $pagesper
и имя исходного PDF-файла в $file
.
number=$(pdfinfo -- "$file" 2> /dev/null | awk '$1 == "Pages:" {print $2}')
count=$((($number+$pagesper-1)/$pagesper))
filename=${file%.pdf}
counter=0
while [ "$count" -gt "$counter" ]; do
start=$((counter*pagesper + 1));
end=$((start + pagesper - 1));
if [ $end -gt $number ]; then
end=$number
fi
counterstring=$(printf %04d "$counter")
pdftk "$file" cat "${start}-${end}" output "${filename}_${counterstring}.pdf"
counter=$((counter + 1))
done
Ответ или решение
Разделение PDF-документов на файлы с определенным количеством страниц представляет собой задачу, с которой могут столкнуться специалисты в области информационных технологий и административные работники. Часто требуется сжать содержимое большого документа, создавая множество меньших файлов для удобства обращения или передачи. В данной справке мы обсудим несколько способов добиться этого.
Теоретические основы
PDF-файлы — это универсальный формат электронных документов, известный своей возможностью сохранять исходное форматирование независимо от устройства или программы просмотра. Однако из-за этой универсальности возникают некоторые сложности при необходимости автоматического разделения документа на части. Основные инструменты работы с PDF, такие как pdftk
, предлагают базовую функциональность, но не все они поддерживают разделение на файлы с фиксированным числом страниц.
Подход с использованием командной строки и pdftk
Первый подход к решению задачи заключается в использовании командной строки и pdftk
. Этот инструмент позволяет извлекать конкретные страницы из большого документа в новый файл. Однако для решения задачи разделения на файлы с несколькими страницами потребуется дополнительная скриптовая логика:
-
Получение общее количество страниц: Используйте
pdfinfo
для извлечения информации о документе, в частности, количеству страниц.number=$(pdfinfo -- "$file" 2> /dev/null | awk '$1 == "Pages:" {print $2}')
-
Настройка скрипта для циклического создания новых документов: Определяется количество файлов, необходимых для полного разделения PDF, и настраивается цикл, который будет обрабатывать каждую группу страниц по отдельности.
while [ "$count" -gt "$counter" ]; do start=$((counter*pagesper + 1)); end=$((start + pagesper - 1)); if [ $end -gt $number ]; then end=$number fi counterstring=$(printf %04d "$counter") pdftk "$file" cat "${start}-${end}" output "${filename}_${counterstring}.pdf" counter=$((counter + 1)) done
Этот метод требует установленных утилит из пакета poppler-utils, включая pdfinfo
и pdftk
.
Использование Python и библиотеки PyPDF2
Альтернативным решением является использование Python с библиотекой PyPDF2. Этот подход дает значительное преимущество в возможностях автоматизации и интеграции в более сложные рабочие процессы.
-
Чтение документа: Сначала открываем оригинальный файл для чтения.
input_pdf = PdfFileReader(open(sys.argv[1], 'rb'))
-
Итерация по страницам и запись в новые файлы: Определяем логики обработки каждой страницы и создания новых файлов на основе указанного количества страниц на файл.
for i in range(num_pages): output_pdf.addPage(input_pdf.getPage(i)) if (i + 1) % pages_per_file == 0 or i + 1 == num_pages: output_file = open(base_name + str(i // pages_per_file + 1) + '.pdf', "wb") output_pdf.write(output_file) output_file.close() output_pdf = PdfFileWriter()
Этот метод является более современным и позволяет легко масштабировать скрипт или интегрировать его в более сложные системы управления документами.
Применение на практике
Выбор наиболее подходящего способа будет зависеть от ваших задач. Если разовая задача требует быстрого решения, подход с использованием pdftk
может быть достаточным. Если же требуется более автоматизированное решение или интеграция в пайплайн обработки данных, то предпочтительнее использовать Python.
Итак, у вас есть несколько методов и сценариев для разделения PDF-документов на части по числу страниц. Выбор подхода будет существенно зависеть от ваших специфических требований и окружения. Завершая, напомним, что владение различными инструментами и знаниями — ключ к успешной и эффективной работе с PDF-документами.