Wie füge ich 2 PDF-Dateien mit der Reihenfolge der verschachtelten Seiten zusammen?

13

Ich habe ein doppelseitig gedrucktes mehrseitiges Dokument zum Scannen mit einem linearen Massenscanner. Als Ergebnis erhalte ich 2 PDF-Dateien: eine mit allen ungeraden Seiten und die zweite mit allen geraden Seiten. Ich muss sie auf natürliche Weise zusammenführen:

1. <- 1.1. (odd.pdf page 1 to result.pdf page 1)
2. <- 2.1. (even.pdf page 1 to result.pdf page 2)
3. <- 1.2. (odd.pdf page 2 to result.pdf page 3)
4. <- 2.2. (even.pdf page 2 to result.pdf page 4)

etc.

Ivan
quelle
Suchen Sie einfach einen PDF-Parser und führen Sie eine Zusammenführungssortierung durch.
Gänseblümchen
1
Wenn Stephane Ihr Problem nicht löst, können Sie das Perl-Modul ausprobieren CAM::PDF. Ich werde Ihnen später ein Skript geben. Haben die beiden PDFs die gleiche Seitenzahl?
Gänseblümchen

Antworten:

7

Siehe die pdfseparateund pdfuniteBefehle von poppler-utils. Die erste, um die Seiten von jedem Dokument in einzelne Dateien zu trennen, und die zweite, um sie in der gewünschten Reihenfolge in einem neuen Dokument zusammenzuführen.

Da Scanner Ihnen ohnehin Rasterbilder liefern (von denen einige wie Ihre zu PDF-Dateien verketten können), können Sie sie möglicherweise so konfigurieren, dass stattdessen Bilder (png, tiff ...) ausgegeben werden, und die Verkettung selbst mit einem PDF durchführen ImageMagick.

Stéphane Chazelas
quelle
Das klingt wie das, was ich brauche, lass es uns versuchen ...
Ivan
1
Tatsächlich. Ausgezeichnet. Einfach zu bedienen, um richtig zu machen, was ich brauche. Übrigens habe ich natürlich gegoogelt, bevor ich gefragt habe, und Lösungen, die ich genau gleich gefunden habe, waren deutlich komplexer.
Ivan
Ich habe dies unter Ubuntu 18.04 versucht (mit dem hilfreichen Skript unten von @TCF) und es hat zwei ~ 5,5-MB-Dateien in eine 197-MB-Datei umgewandelt. Während der Arbeit war es also nicht verwendbar (ich musste das Ergebnis per E-Mail senden!) .
Reuben Thomas
12

pdftk hat einen Shuffle-Befehl, der Seiten sortiert:

pdftk A=odd.pdf B=even.pdf shuffle A B output collated.pdf
djao
quelle
1
Dies funktionierte gut für mich, aber mit einer Optimierung, um die geraden Seiten umzukehren (vorausgesetzt, ich habe sie gescannt, ohne zuerst die Reihenfolge der Seiten umzukehren): pdftk A = recto.pdf B = verso.pdf shuffle Eine Bend-1-Ausgabe wurde zusammengestellt. pdf
Reuben Thomas
Fantastisch, danke - das funktioniert perfekt
Infomaniac
2

Nur ein bashkurzer Schuss mit pdfjam:

Erstellen Sie ein Array von Eingabeargumenten:

for k in $(seq 1 ${N_PAGES}); do
    PAGES+=(odd.pdf);
    PAGES+=($k);
    PAGES+=(even.pdf);
    PAGES+=($k);
done

Dies sollte es Ihnen ermöglichen, es als Eingabeliste zu verwenden für pdfjoin:

 pdfjoin ${PAGES[@]} --outfile shuffled.pdf
fheub
quelle
2
Es sollte beachtet werden, dass pdfjoines sich um ein Wrapper-Skript handelt, um pdfjamdas sich selbst ein Wrapper-Skript um das pdfpagesLaTeX-Paket (und pdflatex) handelt. Dies bedeutet, dass LaTeX als Abhängigkeit verwendet wird.
Stéphane Chazelas
1

Sie können das Mix-Modul in PDFsam Basic (kostenlos und Open Source) verwenden oder es online mit der Alternate & Mix- Funktion in Sejda ausführen

Andrea Vacondio
quelle
1
Zweifellos die beste Lösung: Open Source, keine Installation erforderlich. 2 Klicks und fertig;)
Nathan
0

Ich wollte im Grunde das Gleiche tun, und Stéphane Chazelas 'Antwort war sehr hilfreich. Ich mache das oft genug, dass ich ein einfaches Python-Skript geschrieben habe, um Dinge mit den von ihm vorgeschlagenen Befehlen zu automatisieren. Standardmäßig wird die Reihenfolge der geraden Seiten umgekehrt, dies kann jedoch mit einem Befehlszeilenflag unterdrückt werden.

Die Frage ist ziemlich alt, daher gehe ich davon aus, dass die Bedürfnisse des ursprünglichen Fragestellers bereits erfüllt wurden. Es ist jedoch möglich, dass das Skript für Personen nützlich ist, die in Zukunft hier ankommen. Deshalb habe ich es unten platziert.

#!/usr/bin/python
"""A simple script to merge two PDFs."""

import argparse
from os import listdir
from os.path import join as opjoin
import shutil
from subprocess import check_call, CalledProcessError
import tempfile

SEPARATE = 'pdfseparate %s %s'
MERGE = 'pdfunite %s %s'

def my_exec(command):
    """Execute a command from a shell, ignoring errors."""
    try:
        check_call(command, shell=True)
    except CalledProcessError:
        pass

def run(odd, even, out, reverse_odd=False, reverse_even=True):
    """Interleave odd and even pages from two PDF files."""
    folder = tempfile.mkdtemp()
    my_exec(SEPARATE % (odd, opjoin(folder, 'odd%d.pdf')))
    my_exec(SEPARATE % (even, opjoin(folder, 'even%d.pdf')))
    odd_files = []
    even_files = []
    for curr_file in listdir(folder):
        filepath = opjoin(folder, curr_file)
        if curr_file.startswith('odd'):
            odd_files.append((filepath, int(curr_file[3:-4])))
        elif curr_file.startswith('even'):
            even_files.append((filepath, int(curr_file[4:-4])))
    func = lambda x: x[1]
    odd_files.sort(key=func, reverse=reverse_odd)
    even_files.sort(key=func, reverse=reverse_even)
    parts = []
    for line in zip(odd_files, even_files):
        parts.append(line[0][0])
        parts.append(line[1][0])
    my_exec(MERGE % (' '.join(parts), out))
    shutil.rmtree(folder)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Merge two PDF files.')
    parser.add_argument('odd_pages', help='PDF containing the odd pages.')
    parser.add_argument('even_pages', help='PDF containing the even pages.')
    parser.add_argument('output_file', help='The target output file.')
    parser.add_argument('--reverse-odd', action='store_true', 
                        help='Insert the odd pages in reverse order.')
    parser.add_argument('--no-reverse-even', action='store_true',
                        help='Suppress reversal of the even pages.')
    args = parser.parse_args()
    run(args.odd_pages, args.even_pages, args.output_file,
        args.reverse_odd, not args.no_reverse_even)
TCF
quelle
0

Ich bin dabei auf dieses Bash-Skript gestoßen. Es setzt voraus, dass Sie die geraden Seiten in umgekehrter Reihenfolge gescannt haben. Sie können dies jedoch ändern, indem Sie das -rin der Zeile stehende Sprichwort entfernen evenpages=($(ls "$evenbase-$key-"* | sort -r))(dies ist Zeile 46).

#!/bin/bash
# Copyright Fabien André <[email protected]>
# Distributed under the MIT license
# This script interleaves pages from two distinct PDF files and produces an
# output PDF file. The odd pages are taken from a first PDF file and the even
# pages are taken from a second PDF file passed respectively as first and second
# argument.
# The first two pages of the output file are the first page of the
# odd pages PDF file and the *last* page of the even pages PDF file. The two
# following pages are the second page of the odd pages PDF file and the
# second to last page of the even pages PDF file and so on.
#
# This is useful if you have two-sided documents scanned each side on a
# different file as it can happen when using a one-sided Automatic Document
# Feeder (ADF)
#
# It does a similar job to :
# https://github.com/weltonrodrigo/pdfapi2/blob/46434ab3f108902db2bc49bcf06f66544688f553/contrib/pdf-interleave.pl
# but only requires bash (> 4.0) and poppler utils.
# Print usage/help message
function usage {
echo "Usage: $0 <PDF-even-pages-file> <PDF-odd-pages-file>"
exit 1
}
# Add leading zeros to pad numbers in filenames matching the pattern
# $prefix$number.pdf. This allows filenames to be easily sorted using
# sort.
# $1 : The prefix of the filenames to consider
function add_leading_zero {
prefix=$1
baseprefix=$(basename $prefix | sed -e 's/[]\/()$*.^|[]/\\&/g')
dirprefix=$(dirname $prefix)
for filename in "$prefix"*".pdf"
do
base=$(basename "$filename")
index=$(echo "$base" | sed -rn "s/$baseprefix([0-9]+).pdf$/\1/p")
newbase=$(printf "$baseprefix%04d.pdf" $index)
mv $filename "$dirprefix/$newbase"
done
}
# Interleave pages from two distinct PDF files and produce an output PDF file.
# Note that the pages from the even pages file (second file) will be used in
# the reverse order (last page first).
# $1 : Odd pages filename
# $2 : Odd pages filename with extension removed
# $3 : Even pages filename
# $4 : Even pages filename with extension removed
# $5 : Unique key used for temporary files
# $6 : Output file
function pdfinterleave {
oddfile=$1
oddbase=$2
evenfile=$3
evenbase=$4
key=$5
outfile=$6
# Odd pages
pdfseparate $oddfile "$oddbase-$key-%d.pdf"
add_leading_zero "$oddbase-$key-"
oddpages=($(ls "$oddbase-$key-"* | sort))
# Even pages
pdfseparate $evenfile "$evenbase-$key-%d.pdf"
add_leading_zero "$evenbase-$key-"
evenpages=($(ls "$evenbase-$key-"* | sort -r))
# Interleave pages
pages=()
for((i=0;i<${#oddpages[@]};i++))
do
pages+=(${oddpages[i]})
pages+=(${evenpages[i]})
done
pdfunite ${pages[@]} "$outfile"
rm ${oddpages[@]}
rm ${evenpages[@]}
}
if [ $# -lt 2 ]
then
usage
fi
if [ $1 == $2 ]
then
echo "Odd pages file and even pages file must be different." >&2
exit 1
fi
if ! hash pdfunite 2>/dev/null || ! hash pdfseparate 2>/dev/null
then
echo "This script requires pdfunite and pdfseparate from poppler utils" \
"to be in the PATH. On Debian based systems, they are found in the" \
"poppler-utils package"
exit 1
fi
oddbase=${1%.*}
evenbase=${2%.*}
odddir=$(dirname $oddbase)
oddfile=$(basename $oddbase)
evenfile=$(basename $evenbase)
outfile="$odddir/$oddfile-$evenfile-interleaved.pdf"
key=$(tr -dc "[:alpha:]" < /dev/urandom | head -c 8)
if [ -e $outfile ]
then
echo "Output file $outfile already exists" >&2
exit 1
fi
pdfinterleave $1 $oddbase $2 $evenbase $key $outfile
# SO - Bash command that prints a message on stderr
# http://stackoverflow.com/questions/2643165/bash-command-that-prints-a-message-on-stderr
# SO - Check if a program exists from a bash script
# http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script
# SO - How to debug a bash script?
# http://stackoverflow.com/questions/951336/how-to-debug-a-bash-script
# SO - Escape a string for sed search pattern
# http://stackoverflow.com/questions/407523/escape-a-string-for-sed-search-pattern

Quelle

switch87
quelle