Jak scalić pliki pdf, aby każdy plik zaczynał się na nieparzystym numerze strony?

11

Muszę scalić kilkadziesiąt plików PDF i chcę, aby wszystkie wejściowe pliki PDF zaczynały się na nieparzystej stronie w pliku wyjściowym PDF.

Przykład: A.pdfma 3 strony, B.pdfma 4 strony. Nie chcę, aby mój wynik miał 7 stron. Chcę 8-stronicowego pdf, z którego pochodzą strony 1-3 A.pdf, strona 4 jest pusta, a strony 5-8 B.pdf. W jaki sposób mogę to zrobić?

Wiem o pdftk, ale nie znalazłem takiej opcji na stronie man.

Jan Warchoł
źródło

Odpowiedzi:

6

Biblioteka PyPdf sprawia, że tego rodzaju rzeczy łatwe, jeśli jesteś gotów napisać trochę Pythona. Zapisz poniższy kod w skrypcie o nazwie pdf-cat-even(lub cokolwiek chcesz), ustaw go jako wykonywalny ( chmod +x pdf-cat-even) i uruchom jako filtr ( ./pdf-cat-even a.pdf b.pdf >concatenated.pdf). Potrzebujesz metody 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)
Gilles „SO- przestań być zły”
źródło
Dzięki, to zadziałało dla mnie! Ponieważ wolę czytać nazwy plików pdf z pliku, nieco zmodyfikowałem twój kod i opublikowałem go jako osobną odpowiedź .
Jan Warchoł
@JanekWarchol Jeśli twoje nazwy plików nie zawierają znaków specjalnych powłoki, takich jak białe spacje:./pdf-cat-even $(cat list-of-file-names.txt) >concatenated.pdf
Gilles 'SO- przestań być zły'
Niestety zawierają białe spacje. Niemniej jednak dzięki - nie zdawałem sobie sprawy, że można to zrobić w ten sposób.
Jan Warchoł
@JanekWarchol Następnie możesz użyć<list-of-file-names.txt tr '\n' '\0' | xargs -0 ./pdf-cat-even >concatenated.pdf
Gilles 'SO- przestań być zły'
3

Pierwszym krokiem jest utworzenie pliku pdf z pustą stroną. Możesz to zrobić z łatwością za pomocą wielu programów (LibreOffice / OpenOffice, inkscape, (La) TeX, scribus itp.)

Następnie dołącz tę pustą stronę w razie potrzeby:

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

Jeśli chcesz to zrobić automatycznie za pomocą skryptu, możesz użyć np. pdftk file.pdf dump_data | grep NumberOfPages | egrep -o '[0-9]*'Do wyodrębnienia liczby stron.

Jofel
źródło
To trochę hack. Chociaż jeśli to działa, to chyba działa.
Sam Whited
To podejście prawie dla mnie zadziałało: napisałem skrypt, który wygenerował listę plików pdf z dodanym epmtyPage.pdf, jeśli było to konieczne, ale nie mogłem zmusić pdftk do poprawnego przeanalizowania tej listy, jeśli nazwy plików zawierały spacje. Próbowałem zmienić wartość IFS, używając cudzysłowów, ale bezskutecznie - może to wina pdftk. W każdym razie odpowiedź przy użyciu pypdf działała dla mnie.
Jan Warchoł
@JanekWarchol Z której wersji pdftk korzystałeś? Wydaje się, że przynajmniej pdftk 1.44 i nowsze obsługują białe spacje w nazwach plików.
jofel
@ jofel pdftk --versionzwraca pdftk 1.44. Pamiętam, że moi bardziej doświadczeni bash przyjaciele spędzili co najmniej 15 minut, próbując różnych rzeczy, aby dostać tę pracę i zrezygnowali.
Jan Warchoł
1

Odpowiedź Gillesa działała dla mnie, ale ponieważ muszę scalić wiele plików, wygodniej jest odczytać ich nazwy z pliku tekstowego. Lekko zmodyfikowałem kod Gillesa, aby to zrobić, być może pomogłoby to komuś innemu:

#!/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ł
źródło
1

Możesz również użyć do tego LaTeXa (choć wiem, że prawdopodobnie nie tego chcesz). Powinno działać coś takiego:

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

Pamiętaj, że \cleardoublepagewstawia tylko pustą stronę z klasami, które są przeznaczone do drukowania dwustronnego (np. Książka)

Więcej opcji i informacji pdfpagesmożna znaleźć na stronie CTAN .

Sam Whited
źródło
2
Aby automatycznie uwzględnić wszystkie strony, możesz użyć \includepdf[pages=-]{...}.
jofel
@jofel Dzięki, naprawiłem pytanie. Myślę, że domyślnie są to również wszystkie strony, po prostu umieściłem je tam, aby pokazać, że można było wybrać określone strony.
Sam Whited
@ jofel Ponadto \cleardoublepagewstawia pustą stronę tylko wtedy, gdy używasz klasy przeznaczonej do drukowania dwustronnego. Korzystałem z artykułu, który nie działa; Naprawiłem to i zaktualizowałem pytanie, aby to odzwierciedlić.
Sam Whited
\includepdfdomyślnie zawiera tylko pierwszą stronę (nie wszystkie strony). \documentclass[twoside]{article}działa również.
jofel
Z tego, co widzę, musiałbym jawnie napisać wszystkie pliki, które muszą zostać uwzględnione, więc nie jest to dla mnie wystarczająco dobre. Ale i tak dzięki.
Jan Warchoł
0

Oto kod z PyPDF2 i 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
źródło