¿Cómo fusionar 2 archivos PDF con orden de páginas intercaladas?

13

Tengo un documento de varias páginas impreso en doble cara para escanear con un escáner lineal masivo. Entonces, como resultado, obtengo 2 archivos PDF: uno que contiene todas las páginas impares y el segundo que contiene todas las páginas pares. Necesito fusionarlos de la manera natural:

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
fuente
Simplemente encuentre un analizador de PDF y haga una combinación de cosas como cosas.
Margarita
1
Si Stephane no resuelve su problema, puede probar el módulo perl CAM::PDF, luego le daré un script. ¿Los dos pdf tienen el mismo recuento de páginas?
Margarita

Respuestas:

7

Vea los comandos pdfseparatey pdfunitede poppler-utils. El primero para separar las páginas de cada documento en archivos individuales, y el segundo para fusionarlas en el orden que desee en un nuevo documento.

También tenga en cuenta que, dado que los escáneres le brindan imágenes de trama de todos modos (que algunos como el suyo pueden concatenar en archivos PDF), tal vez pueda configurarlo para que genere imágenes (png, tiff ...) y hacer la concatenación en un PDF usted mismo con ImageMagick.

Stéphane Chazelas
fuente
Esto suena como lo que necesito, intentemos ...
Ivan
1
En efecto. Excelente. Fácil de usar para hacer lo que necesito. Por cierto, he buscado en Google antes de preguntar y las soluciones que encontré exactamente iguales fueron notablemente más complejas.
Ivan
Intenté esto en Ubuntu 18.04 (con el útil script a continuación de @TCF) y convirtió dos archivos de ~ 5.5Mb en un archivo de 197Mb, así que si bien hizo el trabajo, no era utilizable (¡necesitaba enviar el resultado por correo electrónico!) .
Reuben Thomas
12

pdftk tiene un comando aleatorio que recopila páginas:

pdftk A=odd.pdf B=even.pdf shuffle A B output collated.pdf
djao
fuente
1
Esto funcionó bien para mí, pero con un ajuste para invertir las páginas pares (dado que las escaneé sin invertir primero el orden de las páginas): pdftk A = recto.pdf B = verso.pdf shuffle A salida de Bend-1 cotejada. pdf
Reuben Thomas
Fantástico, gracias - esto funciona perfectamente
infomaniac
2

Solo un bashdisparo rápido usando pdfjam:

Construya una matriz de argumentos de entrada:

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

Esto debería permitirle usarlo como lista de entrada para pdfjoin:

 pdfjoin ${PAGES[@]} --outfile shuffled.pdf
fheub
fuente
2
Cabe señalar que pdfjoines una secuencia de comandos de envoltura alrededor de la pdfjamcual es una secuencia de comandos de envoltura alrededor del pdfpagespaquete LaTeX (y pdflatex), por lo que significa que trae LaTeX como una dependencia.
Stéphane Chazelas
1

Puede usar el módulo Mix en PDFsam Basic (gratuito y de código abierto) o hacerlo en línea usando la función Alternate & Mix en Sejda

Andrea Vacondio
fuente
1
Sin duda, la mejor solución: código abierto, no requiere instalación. 2 clics y listo;)
nathan
0

Estaba buscando hacer básicamente lo mismo, y la respuesta de Stéphane Chazelas fue muy útil. Hago esto con la frecuencia suficiente para escribir un simple script de Python para automatizar las cosas, usando los comandos que sugirió. Por defecto, invierte el orden de las páginas pares, pero esto se puede suprimir con un indicador de línea de comando.

La pregunta es un poco antigua, por lo que espero que las necesidades del autor de la pregunta original ya se hayan cumplido. Sin embargo, es posible que el script sea útil para las personas que lleguen aquí en el futuro, por lo que lo he colocado a continuación.

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

Me encontré con este script de bash haciendo esto, se supone que escaneó las páginas pares en orden inverso, pero puede cambiar esto eliminando el dicho -ren la línea evenpages=($(ls "$evenbase-$key-"* | sort -r))(esta es la línea 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

Fuente

switch87
fuente