Bagaimana cara menggabungkan 2 file PDF dengan urutan halaman yang disisipkan?

13

Saya punya dokumen multi sisi yang dicetak dua sisi untuk dipindai dengan pemindai massal linier. Jadi, sebagai hasilnya saya mendapatkan 2 file PDF: satu berisi semua halaman ganjil dan yang kedua berisi semua halaman genap. Saya perlu menggabungkan mereka dengan cara alami:

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)

dll.

Ivan
sumber
Cukup temukan parser PDF dan lakukan semacam penggabungan hal-hal.
Daisy
1
Jika Stephane tidak menyelesaikan masalah Anda, Anda dapat mencoba modul perl CAM::PDF, saya akan memberikan skrip Anda nanti. Apakah kedua pdf ini memiliki jumlah halaman yang sama?
Daisy

Jawaban:

7

Lihat pdfseparatedan pdfuniteperintah dari poppler-utils. Yang pertama untuk memisahkan halaman dari setiap dokumen menjadi file individual, dan yang kedua untuk menggabungkannya dalam urutan yang Anda inginkan dalam dokumen baru.

Juga perhatikan bahwa karena pemindai memberi Anda gambar raster (yang beberapa orang seperti milik Anda dapat digabungkan menjadi file PDF), mungkin Anda dapat mengonfigurasinya untuk menghasilkan gambar (png, tiff ...), dan lakukan penggabungan ke dalam PDF dengan ImageMagick.

Stéphane Chazelas
sumber
Ini kedengarannya seperti yang saya butuhkan, mari kita coba ...
Ivan
1
Memang. Luar biasa. Mudah digunakan untuk melakukan apa yang saya butuhkan. Ngomong-ngomong, saya, tentu saja, sudah mencari di Google sebelum bertanya dan solusi yang saya temukan persis sama ternyata lebih kompleks.
Ivan
Saya mencoba ini di Ubuntu 18.04 (dengan skrip yang membantu di bawah ini dari @TCF) dan ternyata dua ~ 5,5 MB file menjadi satu file 197 MB, jadi sementara itu melakukan pekerjaan, itu tidak dapat digunakan (saya perlu mengirim email hasilnya!) .
Ruben Thomas
12

pdftk memiliki perintah acak yang menyusun halaman:

pdftk A=odd.pdf B=even.pdf shuffle A B output collated.pdf
djao
sumber
1
Ini bekerja dengan baik untuk saya, tetapi dengan tweak untuk membalik halaman genap (mengingat bahwa saya memindai mereka tanpa terlebih dahulu membalik urutan halaman): pdftk A = recto.pdf B = verso.pdf shuffle A Bend-1 output disusun. pdf
Reuben Thomas
Fantastis, terima kasih - ini berfungsi dengan baik
infomaniac
2

Hanya bashbidikan cepat menggunakan pdfjam:

Buat array argumen input:

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

Ini akan memungkinkan Anda untuk menggunakannya sebagai daftar input untuk pdfjoin:

 pdfjoin ${PAGES[@]} --outfile shuffled.pdf
fheub
sumber
2
Perlu dicatat bahwa pdfjoinskrip pembungkus di sekitarnya pdfjamyang merupakan skrip pembungkus di sekitar pdfpagespaket LaTeX (dan pdflatex) sehingga artinya membawa LaTeX sebagai ketergantungan.
Stéphane Chazelas
1

Anda dapat menggunakan modul Mix dalam PDFsam Basic (sumber gratis dan terbuka) atau melakukannya secara online menggunakan fitur Alternate & Mix di Sejda

Andrea Vacondio
sumber
1
Hands down solusi terbaik: open source, tidak perlu instalasi. 2 klik dan selesai;)
nathan
0

Pada dasarnya saya ingin melakukan hal yang sama, dan jawaban Stéphane Chazelas sangat membantu. Saya cukup sering melakukan ini sehingga saya menulis skrip Python sederhana untuk mengotomatisasi sesuatu, menggunakan perintah yang disarankannya. Secara default, ini membalik urutan halaman genap, tetapi ini dapat ditekan dengan bendera baris perintah.

Pertanyaannya agak lama, jadi saya berharap kebutuhan penanya yang asli sudah terpenuhi. Namun, mungkin saja skrip akan berguna bagi orang-orang yang tiba di sini di masa depan, jadi saya telah menempatkannya di bawah.

#!/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
sumber
0

Saya menemukan skrip bash ini dengan melakukan ini, ini mengasumsikan Anda memindai halaman genap dalam urutan terbalik, tetapi Anda dapat mengubah ini dengan menghapus -rbaris yang bertuliskan evenpages=($(ls "$evenbase-$key-"* | sort -r))(ini baris 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

Sumber

saklar87
sumber