Como posso mesclar arquivos PDF para que cada arquivo comece com um número de página ímpar?

11

Preciso mesclar alguns PDFs cochilados e quero que todos os PDFs de entrada iniciem em uma página ímpar no PDF de saída.

Exemplo: A.pdftem 3 páginas, B.pdftem 4 páginas. Eu não quero que a minha saída para ter 7 páginas. O que eu quero é um pdf de 8 páginas no qual as páginas 1-3 são A.pdf, a página 4 está vazia e as páginas 5-8 B.pdf. Como posso fazer isso?

Eu sei sobre o pdftk, mas não encontrei essa opção na página de manual.

Jan Warchoł
fonte

Respostas:

6

A biblioteca PyPdf facilita esse tipo de coisa se você estiver disposto a escrever um pouco de Python. Salve o código abaixo em um script chamado pdf-cat-even(ou o que você quiser), torne-o executável ( chmod +x pdf-cat-even) e execute-o como um filtro ( ./pdf-cat-even a.pdf b.pdf >concatenated.pdf). Você precisa de pyPdf ≥1,13 para o addBlankPagemétodo.

#!/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)
Gilles 'SO- parar de ser mau'
fonte
Obrigado, isso funcionou para mim! Como prefiro ler os nomes dos PDFs de um arquivo, modifiquei um pouco o código e postei-o como uma resposta separada .
Jan Warchoł
@JanekWarchol Se os nomes dos seus arquivos não contiverem caracteres especiais como: espaço em branco:./pdf-cat-even $(cat list-of-file-names.txt) >concatenated.pdf
Gilles 'SO- stop be evil'
Infelizmente, eles contêm espaços em branco. Mas, no entanto, obrigado - eu não sabia que isso poderia ser feito dessa maneira.
Jan Warchoł
@JanekWarchol Então você pode usar<list-of-file-names.txt tr '\n' '\0' | xargs -0 ./pdf-cat-even >concatenated.pdf
Gilles 'SO- stop
3

O primeiro passo é produzir um arquivo pdf com uma página vazia. Você pode fazer isso facilmente com muitos programas (LibreOffice / OpenOffice, inkscape, (La) TeX, scribus etc.)

Em seguida, inclua esta página vazia onde for necessário:

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

Se você quiser fazer isso automaticamente com um script, poderá usar, por exemplo, pdftk file.pdf dump_data | grep NumberOfPages | egrep -o '[0-9]*'para extrair a contagem de páginas.

jofel
fonte
Isso parece um pouco de hack. Embora, se funcionar, suponha que funcione.
Sam Whited
Essa abordagem quase funcionou para mim: escrevi um script que produzia uma lista de PDFs com o epmtyPage.pdf adicionado quando necessário, mas não consegui que o pdftk analise corretamente essa lista se os nomes de arquivos contiverem espaços. Tentei alterar o valor do IFS usando aspas, mas sem sucesso - talvez seja culpa do pdftk. Enfim, a resposta usando pypdf funcionou para mim.
Jan Warchoł
@JanekWarchol Qual versão do pdftk você usou? Pelo menos o pdftk 1.44 e mais recente parece oferecer suporte a espaços em branco nos nomes de arquivos.
Jofel
@jofel pdftk --versionretorna o pdftk 1.44. Lembro que meus amigos mais experientes passaram pelo menos 15 minutos tentando coisas diferentes para conseguir esse trabalho e desistiram.
Jan Warchoł
1

A resposta de Gilles funcionou para mim, mas como tenho que mesclar muitos arquivos, é mais conveniente poder ler os nomes deles em um arquivo de texto. Modifiquei levemente o código de Gilles para fazer exatamente isso, talvez ajude alguém:

#!/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)
Jan Warchoł
fonte
1

Você também pode usar o LaTeX para fazer isso (embora eu saiba que provavelmente não é o que você deseja). Algo como o seguinte deve funcionar:

\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}

Observe que \cleardoublepageapenas insere uma página em branco com classes criadas para impressão em frente e verso (por exemplo, livro)

Mais opções e informações pdfpagespodem ser encontradas no CTAN .

Sam Whited
fonte
2
Para incluir todas as páginas automaticamente, você pode usar \includepdf[pages=-]{...}.
Jofel
@jofel Obrigado, corrigiu a pergunta. Eu acho que o padrão é para todas as páginas também, eu apenas o coloquei lá para mostrar que era possível selecionar determinadas páginas.
Sam Whited
@jofel Além disso, \cleardoublepagesomente insere uma página em branco se você estiver usando uma classe criada para impressão em frente e verso. Eu estava usando um artigo que não funciona; Corrigi e atualizei a pergunta para refletir isso.
Sam Whited
\includepdfinclui apenas a primeira página por padrão (nem todas as páginas). \documentclass[twoside]{article}funciona também.
Jofel
Pelo que vejo, eu teria que escrever explicitamente todos os arquivos que precisam ser incluídos, para que isso não seja bom o suficiente para mim. Mas obrigada mesmo assim.
Jan Warchoł
0

Aqui está o código com PyPDF2 e 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"))
Loren
fonte