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.

/ 5
Grazie per aver votato!

How useful was this post?

Click on a star to rate it!

Average rating / 5. Vote count:

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?