Come verificare da linea di comando in Linux se un file PDF è corrotto, e come ripararlo.
Potremmo aver l'esigenza di verificare se uno o più file PDF sono integri o corrotti.
Ho pensato a questo articolo dopo un caso reale: avevo un backup di documenti pdf, spostato negli anni tra diversi device USB, e mi sono accorto aprendoli ad uno ad uno della presenza di alcuni file danneggiati.
Vediamo come automatizzare questo processo di verifica, anzichè verificarli a mano.
Il mio ambiente di lavoro è AlmaLinux (Centos, derivate Red Hat) per cui quanto seguirà sarà rivolto a questa distribuzione.
Ti propongo tre strumenti di verifica:
- pdfinfo
- pdftotext
- qpdf
pdfinfo
Questa utility è contenuta all'interno della libreria poppler-utils, per cui procediamo alla sua installazione tramite yum.
yum install poppler-utils
#yum install poppler-utils
Ultima verifica della scadenza dei metadati: 2:37:33 fa il mer 15 giu 2022 09:38:59 CEST.
Dipendenze risolte.
============================================================================================================
Package Architecture Version Repository Size
============================================================================================================
Installing:
poppler-utils x86_64 20.11.0-4.el8 appstream 246 k
Installazione dipendenze:
poppler x86_64 20.11.0-4.el8 appstream 1.1 M
poppler-data noarch 0.4.9-1.el8 appstream 2.1 M
Riepilogo della transazione
============================================================================================================
Installati 3 pacchetti
Dimensione totale dello scaricamento: 3.4 M
Dimensione installata: 16 M
Procedere [s/N]: s
Scaricamento dei pacchetti:
(1/3): poppler-utils-20.11.0-4.el8.x86_64.rpm 373 kB/s | 246 kB 00:00
(2/3): poppler-20.11.0-4.el8.x86_64.rpm 717 kB/s | 1.1 MB 00:01
(3/3): poppler-data-0.4.9-1.el8.noarch.rpm 1.3 MB/s | 2.1 MB 00:01
------------------------------------------------------------------------------------------------------------
Totale 1.4 MB/s | 3.4 MB 00:02
Esecuzione del controllo di transazione
Controllo di transazione eseguito con successo.
Test di transazione in corso
Test di transazione eseguito con successo
Transazione in corso
Preparazione in corso : 1/1
Installing : poppler-data-0.4.9-1.el8.noarch 1/3
Installing : poppler-20.11.0-4.el8.x86_64 2/3
Esecuzione scriptlet in corso: poppler-20.11.0-4.el8.x86_64 2/3
Installing : poppler-utils-20.11.0-4.el8.x86_64 3/3
Esecuzione scriptlet in corso: poppler-utils-20.11.0-4.el8.x86_64 3/3
Verifica in corso : poppler-20.11.0-4.el8.x86_64 1/3
Verifica in corso : poppler-data-0.4.9-1.el8.noarch 2/3
Verifica in corso : poppler-utils-20.11.0-4.el8.x86_64 3/3
Installati:
poppler-20.11.0-4.el8.x86_64 poppler-data-0.4.9-1.el8.noarch poppler-utils-20.11.0-4.el8.x86_64
Fatto!
Ultimata l'installazione, verifichiamo l'integrità di un file PDF digitando pdfinfo seguito dal file, o meglio dal suo path assoluto, che vogliamo verificare
pdfinfo /var/www/html/docs/2593.pdf
Questa la risposta se il file è valido.
#pdfinfo /var/www/html/docs/2593.pdf
Creator: Crystal Reports
Producer: Powered By Crystal
Tagged: no
UserProperties: no
Suspects: no
Form: none
JavaScript: no
Pages: 1
Encrypted: no
Page size: 612 x 792 pts (letter)
Page rot: 0
File size: 76174 bytes
Optimized: no
PDF version: 1.7
Ecco invece un esempio di risposta se il file è corrotto
#pdfinfo /var/www/html/docs/2593.pdf
Syntax Error: Couldn't find trailer dictionary
Syntax Error: Catalog object is wrong type (cmd)
Syntax Error: Couldn't read page catalog
Vediamo con un bash script come verificare massivamente tutti i files contenuti in una directory, per ottenere un elenco di file danneggiati:
#!/bin/sh
cd /var/www/html/docs
for f in *.pdf; do
if ! pdfinfo "$f" &> /dev/null; then
echo "$f" is broken
fi
done
Questro strumento tuttavia spesso non rileva la presenza di un errore, per cui procediamo con altri strumenti.
pdftotext
Altro strumento contenuto nella libreria poppler-utils è pdftotext. In realtà serve a convertire un PDF in un file di testo semplice. Noi lo utilizziamo per verificare se un file è corrotto.
Avendo già installato la libreria, procediamo con la verifica dei file digitando pdftotext seguito dal path del file.
pdftotext /var/www/html/docs/2593.pdf
In presenza di errori nel file, questi verranno elencati, come visto nello strumento precedente.
Ecco un esempio di un suo utilizzo in uno script bash
#!/bin/sh
cd /var/www/html/docs
for f in *.pdf; do
if pdftotext "$f" - &> /dev/null; then
echo "$f" was ok;
else
echo "$f" is broken;
fi;
done
Esattamente come lo strumento precedente, anche questo potrebbe non rilevare errori nei file.
qpdf
Ultimo strumento che vediamo è qpdf. Va installato tramite yum.
yum install qpdf
# yum install qpdf
Ultima verifica della scadenza dei metadati: 2:51:36 fa il mer 15 giu 2022 09:38:59 CEST.
Dipendenze risolte.
============================================================================================================
Package Architecture Version Repository Size
============================================================================================================
Installing:
qpdf x86_64 7.1.1-10.el8 appstream 61 k
Installazione dipendenze:
qpdf-libs x86_64 7.1.1-10.el8 appstream 337 k
Riepilogo della transazione
============================================================================================================
Installati 2 pacchetti
Dimensione totale dello scaricamento: 398 k
Dimensione installata: 1.2 M
Procedere [s/N]: s
Scaricamento dei pacchetti:
(1/2): qpdf-7.1.1-10.el8.x86_64.rpm 294 kB/s | 61 kB 00:00
(2/2): qpdf-libs-7.1.1-10.el8.x86_64.rpm 275 kB/s | 337 kB 00:01
------------------------------------------------------------------------------------------------------------
Totale 194 kB/s | 398 kB 00:02
Esecuzione del controllo di transazione
Controllo di transazione eseguito con successo.
Test di transazione in corso
Test di transazione eseguito con successo
Transazione in corso
Preparazione in corso : 1/1
Installing : qpdf-libs-7.1.1-10.el8.x86_64 1/2
Esecuzione scriptlet in corso: qpdf-libs-7.1.1-10.el8.x86_64 1/2
Installing : qpdf-7.1.1-10.el8.x86_64 2/2
Esecuzione scriptlet in corso: qpdf-7.1.1-10.el8.x86_64 2/2
Verifica in corso : qpdf-7.1.1-10.el8.x86_64 1/2
Verifica in corso : qpdf-libs-7.1.1-10.el8.x86_64 2/2
Installati:
qpdf-7.1.1-10.el8.x86_64 qpdf-libs-7.1.1-10.el8.x86_64
Fatto!
Per verificare l'integrità di un file, utilizza il comando qpdf seguito da --check ed infine dal path del file
qpdf --check /var/www/html/docs/2593.pdf
Ecco un esempio di risposta in caso di file corrotto
# qpdf --check /var/www/html/docs/2593.pdf
WARNING: /var/www/html/docs/2593.pdf: file is damaged
Per verificare tutti i pdf presenti in una directory utilizziamo questo bash script
#!/bin/sh
cd /var/www/html/docs
for file in *
do
if stderr=$((\
qpdf --check $file) 2>&1 >/dev/null) && test -z "$stderr"
then
echo 'file is ok'
else
echo 'file is NOT OK'
fi
done
Nessuno di questi tre strumenti visti è infallibile, potrebbero infatti dare dei falsi positivi, per cui utilizziamo tutti assieme, così
#!/bin/sh
cd /var/www/html/docs
for file in *
do
if stderr=$((\
pdfinfo $file && \
pdftotext -layout $file - && \
qpdf --check $file) 2>&1 >/dev/null) && test -z "$stderr"
then
echo 'file is ok'
else
echo 'file is NOT OK'
fi
Adesso vediamo come correggere un file che dalle nostre verifiche risulta danneggiato.
Correggere un file danneggiato con Ghostscript
Ghostscript è un insieme di strumenti che si utilizza quando si lavora con file PDF e PostScript.
In presenza di un file corrotto, o che presenta dei WARNING nei controlli effettuati con gli strumenti appena visti, possiamo provare a dare in pasto a Ghostscript il file e vedere se è in grado di risolvere i suoi problemi.
Ad esempio, usando qpdf, ho ottenuto questi warning
#qpdf --check /var/www/html/docs/2593.pdf
checking /var/www/html/docs/2593.pdf
PDF Version: 1.4
File is not encrypted
File is linearized
WARNING: page 0 has shared identifier entries
WARNING: page 0: shared object 6: in hint table but not computed list
Proviamo a correggere questi problemi lanciando Ghostscript, con il comando gs, indicando il file originario da correggere ed il file corretto da ottenere. Ti consiglio di dare un nome diverso ai due file, o conservare un backup del file originario.
# gs -o /var/www/html/docs/correct.pdf -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress /var/www/html/docs/2593.pdf
GPL Ghostscript 9.27 (2019-04-04)
Copyright (C) 2018 Artifex Software, Inc. All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
Processing pages 1 through 1.
Page 1
Adesso proviamo a verificare il nuovo file ottenuto usando sempre qpdf ...
# qpdf --check /var/www/html/docs/correct.pdf
checking /var/www/html/docs/correct.pdf
PDF Version: 1.7
File is not encrypted
File is not linearized
No syntax or stream encoding errors found; the file may still contain
errors that qpdf cannot detect
Ottimo lavoro Ghostscript, I warning sono spariti!
Dopo questo articolo spero tu abbia voglia di sperimentare ed approfondire gli spunti acquisiti.