Làm cách nào để hợp nhất 2 tệp PDF với thứ tự các trang xen kẽ?


13

Tôi đã có một tài liệu nhiều trang được in hai mặt để quét bằng máy quét số lượng lớn tuyến tính. Vì vậy, kết quả là tôi nhận được 2 tệp PDF: một tệp chứa tất cả các trang lẻ và thứ hai chứa tất cả các trang chẵn. Tôi cần hợp nhất chúng theo cách tự nhiên:

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)

Vân vân.


Chỉ cần tìm một trình phân tích cú pháp PDF và thực hiện sắp xếp hợp nhất như công cụ.
cúc

1
Nếu Stephane không giải quyết được vấn đề của bạn, bạn có thể thử mô-đun perl CAM::PDF, tôi sẽ cung cấp cho bạn một tập lệnh sau. Hai pdf có cùng số trang không?
cúc

Câu trả lời:


7

Xem pdfseparatepdfunitecác lệnh từ poppler-utils. Trang đầu tiên tách các trang từ mỗi tài liệu thành các tệp riêng lẻ và trang thứ hai để hợp nhất chúng theo thứ tự bạn muốn trong tài liệu mới.

Cũng lưu ý rằng vì dù sao máy quét cũng cung cấp cho bạn hình ảnh raster (mà một số người như bạn có thể ghép thành tệp PDF), nên có thể bạn có thể định cấu hình nó để xuất hình ảnh (png, tiff ...) và tự mình ghép thành một tệp PDF ImageMagick.


Điều này nghe có vẻ như những gì tôi cần, chúng ta hãy thử ...
Ivan

1
Thật. Thông minh. Đơn giản để sử dụng để làm đúng những gì tôi cần. Nhân tiện, tất nhiên, tôi đã googled trước khi hỏi và các giải pháp tôi thấy giống hệt nhau là phức tạp hơn đáng kể.
Ivan

Tôi đã thử điều này trên Ubuntu 18.04 (với tập lệnh hữu ích bên dưới từ @TCF) và nó đã biến hai tệp ~ 5,5Mb thành một tệp 197Mb, vì vậy trong khi thực hiện công việc, nó không thể sử dụng được (tôi cần gửi email kết quả!) .
Reuben Thomas

12

pdftk có lệnh xáo trộn đối chiếu các trang:

pdftk A=odd.pdf B=even.pdf shuffle A B output collated.pdf

1
Điều này hoạt động tốt với tôi, nhưng với một tinh chỉnh để đảo ngược các trang chẵn (cho rằng tôi đã quét chúng mà không đảo ngược thứ tự của các trang): pdftk A = ortho.pdf B = Verso.pdf xáo trộn Đầu ra uốn cong 1. pdf
Reuben Thomas

Tuyệt vời, cảm ơn - điều này hoạt động hoàn hảo
infomaniac

2

Chỉ cần một bashcú đánh nhanh bằng cách sử dụng pdfjam:

Xây dựng một loạt các đối số đầu vào:

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

Điều này sẽ cho phép bạn sử dụng nó làm danh sách đầu vào cho pdfjoin:

 pdfjoin ${PAGES[@]} --outfile shuffled.pdf

2
Cần lưu ý rằng đó pdfjoinlà một tập lệnh bao bọc pdfjammà chính nó là tập lệnh bao quanh pdfpagesgói LaTeX (và pdflatex) vì vậy nó có nghĩa là nó mang LaTeX làm phụ thuộc.
Stéphane Chazelas

1

Bạn có thể sử dụng mô-đun Mix trong PDFsam Basic (nguồn mở và miễn phí) hoặc thực hiện trực tuyến bằng tính năng Alternate & Mix trong Sejda


1
Giải pháp tốt nhất: mã nguồn mở, không cần cài đặt. 2 lần nhấp và thực hiện;)
nathan

0

Về cơ bản, tôi đang tìm cách làm điều tương tự và câu trả lời của Stéphane Chazelas rất hữu ích. Tôi làm điều này thường xuyên đến mức tôi đã viết một tập lệnh Python đơn giản để tự động hóa mọi thứ, sử dụng các lệnh mà anh ấy đề xuất. Theo mặc định, nó đảo ngược thứ tự của các trang chẵn, nhưng điều này có thể bị chặn bằng cờ dòng lệnh.

Câu hỏi là loại cũ, vì vậy tôi mong rằng nhu cầu của người hỏi ban đầu đã được đáp ứng. Tuy nhiên, có thể kịch bản sẽ hữu ích cho những người đến đây trong tương lai, vì vậy tôi đã đặt nó bên dưới.

#!/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)

0

Tôi đã bắt gặp tập lệnh bash này, nó giả sử bạn đã quét các trang chẵn theo thứ tự ngược lại, nhưng bạn có thể thay đổi điều này bằng cách xóa dòng -rtrong dòng evenpages=($(ls "$evenbase-$key-"* | sort -r))này (đây là dòng 46)

#!/bin/bash
# Copyright Fabien André <fabien.andre@xion345.info>
# 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

Nguồn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.