martedì 26 ottobre 2010

Confrontare le differenze fra due documenti PDF

Nota: qui suggerisco il programma a interfaccia grafica DiffPDF che permette di effettuare un confronto più efficace fra due documenti PDF.

Un semplice metodo per confrontare due documenti in formato PDF è sfruttare l'accoppiata pdftotext (per convertire i PDF in testo puro) + diff (per controllare le differenze). Mi ero stancato di eseguire tutti i soliti comandi allora ho scritto questo script fresco fresco:
#!/bin/bash

function converti() {
    txt=$(eval "expr \$"$1" ")
    pdf=$(eval "expr \$"$2" ")
    scelta=""
    while [ -f "$txt" ]; do
        read -p "Il file $txt esiste già, sovrascriverlo? [s/n]: " scelta
        case "$scelta" in
            s|S|y|Y)
                break 2
                ;;
            n|N)
                read -p "Specifica un file di output differente: " txt
                ;;
        esac
    done
    if ! pdftotext "$pdf" "$txt"; then
        exit 1
    fi
    eval "$1=$txt"
}

if [ $# -ne 2 ]; then
    echo "Uso: $0 PDF1 PDF2"
    exit 1
fi
pdf1=$1
pdf2=$2
txt1=$(dirname "$pdf1")/$(basename "$pdf1" .pdf).txt
txt2=$(dirname "$pdf1")/$(basename "$pdf2" .pdf).txt
converti txt1 pdf1 && converti txt2 pdf2
if [ $? -eq 0 ]; then
    diff -u "$txt1" "$txt2" | less
fi
rm -f "$txt1" "$txt2"
exit 0
Per utilizzarlo basta copiare lo script in un file con un editor di testo a piacere, salvare il file chiamandolo, per esempio, pdf-diff, renderlo eseguibile e posizionarlo nella cartella ~/bin (ricordo che la tilde ~ è un'abbreviazione della cartella home dell'utente corrente), creandola se eventualmente non esiste. Date nel terminale il comando
. ~/.profile
(per i curiosi serve a caricare il file ~/.profile che aggiunge la cartella $HOME/bin alla variabile d'ambiente $PATH), dopo di ciò dovrebbe essere sufficiente dare nel terminale il comando
pdf-diff /percorso/del/primo/file /percorso/del/secondo/file
(o il nome che avete dato allo script).

Non sarà perfetto, ha tutti i limiti che si riscontrano nel passaggio da un PDF a un file di testo puro (per esempio se cambia un'immagine non se ne accorge e la buona riuscita del confronto dipende da quanto bene pdftotext riesce a leggere i documenti) ma è abbastanza veloce e ho trovato questo sistema spesso molto utile.

Ho scritto anche il corrispondente script Nautilus (utilizza zenity):
#!/bin/bash

titolo="Confronto PDF"

function converti() {
    txt=$(eval "expr \$"$1" ")
    pdf=$(eval "expr \$"$2" ")
    while [ -f "$txt" ]; do
        if ! zenity --question --title="$titolo" --text="Il file $txt esiste già, sovrascriverlo?"; then
            txt=$(zenity --entry  --title="$titolo" --text="Specifica un file di output differente: ")
        else
            break 2
        fi
    done
    pdftotext "$pdf" "$txt"
    case $? in
        0)
            ;;
        1)
            zenity --error  --title="$titolo" --text="Si è verificato un errore nell'apertura di $pdf."
            exit 1
            ;;
        2)
            zenity --error  --title="$titolo" --text="Si è verificato un errore nell'apertura di $txt."
            exit 1
            ;;
        3)
            zenity --error  --title="$titolo" --text="Si è verificato un errore collegato ai permessi di $pdf."
            exit 1
            ;;
        *)
            zenity --error  --title="$titolo" --text="Si è verificato un errore!"
            exit 1
    esac
    eval "$1=$txt"
}

if [ $# -ne 2 ]; then
    zenity --error --title="$titolo" --text="Devi selezionare due file alla volta"
    exit 1
fi
pdf1=$1
pdf2=$2
txt1=$(dirname "$pdf1")/$(basename "$pdf1" .pdf).txt
txt2=$(dirname "$pdf1")/$(basename "$pdf2" .pdf).txt
converti txt1 pdf1 && converti txt2 pdf2
if [ $? -eq 0 ]; then
    diff -u "$txt1" "$txt2" | zenity --text-info  --title="$titolo" --filename=/dev/stdin
    rm -f "$txt1" "$txt2"
else # non dovrebbe arrivare mai qui, metto per sicurezza
    zenity --error  --title="$titolo" --text="Si è verificato un errore!"
    exit 1
fi
exit 0
Per utilizzare questo secondo script aprite un file vuoto con un editor di testo, copiate lo script nell'editor e salvatelo nella cartella ~/.gnome2/nautilus-scripts chiamandolo, per esempio, "Confronta PDF". Rendete quindi eseguibile lo script. Così potrete selezionare due file PDF da confrontare e, facendo clic con il tasto destro, scegliete ScriptConfronta PDF (o il nome che avete dato allo script).

Dal punto di vista tecnico, gli script presentano un aspetto un po' particolare: la funzione converti (che serve per convertire il pdf in testo ed eseguire i controlli del caso) presenta una sorta di passaggio di variabile per riferimento e non per valore. Il "trucco" sta nel passare alla funzione non il valore della variabile ma il suo nome (chi ha familiarità con altri linguaggi di programmazione potrebbe trovare ciò naturale). I dettagli possono essere visti qui: http://www.pluto.it/files/ildp/guide/abs/functions.html#DEREFERENCECL.

Nessun commento:

Posta un commento

I commenti inseriti vengono lasciati dall'autore degli stessi accettandone ogni eventuale responsabilità civile e penale.
Il curatore del blog si riserva la possibilità di eliminare messaggi contenenti frasi offensive o spam.