Validar / verificar la integridad de los archivos PDF

11

¿Existe alguna herramienta que pueda ejecutar en los archivos PDF (todos los directorios) y finalmente enumera / identifica los PDF corruptos / inválidos?

Tengo cientos de archivos PDF (relacionados con la documentación, etc.) en mi computadora (máquina Windows), y muy a menudo recibo / tengo que enviar docenas de archivos PDF por correo electrónico. Ahora es una rutina normal que el PDF que recibo o envío está dañado. Esto crea serios problemas a veces, cuando el archivo fuente (por ejemplo, el archivo Word o el archivo Tex falta / no está disponible al instante).

No es posible verificar estos miles de archivos PDF en un tiempo finito, así que busqué una herramienta que pueda ejecutar una vez y escanee todos los archivos PDF (en directorios y subdirectorios), y finalmente obtengo una lista de esos archivos que debo volver a consultar. -crear. Hasta ahora, parece que no existe tal herramienta.

Almirante
fuente
2
Si estás en Linux prueba con pdfinfo. Echar un vistazo a: superuser.com/questions/580887/...
marcwho

Respuestas:

6

Es bastante fácil verificar si un archivo PDF es válido, utilizando PDFtk. Una interfaz gráfica de usuario gratuita para PDFtk está disponible en PDF Labs . Cuando ejecuta esta herramienta, puede cargar tantos PDF como desee, desde múltiples directorios (mediante el botón Agregar archivos), y luego comenzará a acceder a las páginas de estos archivos PDF, muy rápidamente.

Si algún archivo entre los PDF seleccionados no es PDF válido, esta utilidad mostrará un mensaje sobre el error y lo eliminará automáticamente de la ventana de selección.

Por lo tanto, puede ahorrar muchas horas utilizando este procedimiento con PDFtk. Además, si tiene una CPU multinúcleo, puede ejecutar varias instancias de esta utilidad y agregar cientos de archivos PDF en cada instancia.

Estoy usando este software desde el último año, y es la herramienta PDF más útil que he usado.

Mubeen Shahid
fuente
2
Alternativamente, utilizando la herramienta (pdfinfo.exe) disponible en el enlace mencionado por marcwho, puede cdingresar FolderContainingPDFsy ejecutar el siguiente comando en el shell de Windows, y marcará el archivo PDF no válido en un archivo de registro: FORFILES /S /M *.pdf /C "cmd /c echo. & echo @path @fname & D:\XPDF_3.04\bin64\pdfinfo.exe @file" 1>text.txt 2>&1
Mubeen Shahid
4

He usado "pdfinfo.exe" del paquete xpdfbin-win y cpdf.exe para verificar si los archivos PDF están dañados, pero no quería involucrar un binario si no fuera necesario.

Leí que los formatos PDF más nuevos tienen un catálogo de datos xml legible al final, así que abrí el PDF con Windows normal NOTEPAD.exe y me desplacé hacia abajo hasta los datos ilegibles hasta el final y vi varias claves legibles. Solo necesitaba una clave, pero elegí usar CreationDate y ModDate.

El siguiente script de Powershell (PS) verificará TODOS los archivos PDF en el directorio actual y mostrará el estado de cada uno en un archivo de texto (! RESULTS.log). Tomó alrededor de 2 minutos ejecutar esto contra 35,000 archivos PDF. Traté de agregar comentarios para aquellos que son nuevos en PS. Espero que esto ahorre algo de tiempo. Probablemente haya una mejor manera de hacer esto, pero esto funciona perfectamente para mis propósitos y maneja los errores en silencio. Es posible que deba definir lo siguiente al principio: $ ErrorActionPreference = "SilentlyContinue" si ve errores en la pantalla.

Copie lo siguiente en un archivo de texto y asígnele un nombre apropiado (por ejemplo: CheckPDF.ps1) o abra PS y busque el directorio que contiene los archivos PDF para verificar y pegarlo en la consola.

#
# PowerShell v4.0
#
# Get all PDF files in current directory
#
$items = Get-ChildItem | Where-Object {$_.Extension -eq ".pdf"}

$logFile = "!RESULTS.log"
$badCounter = 0
$goodCounter = 0
$msg = "`n`nProcessing " + $items.count + " files... "
Write-Host -nonewline -foregroundcolor Yellow $msg
foreach ($item in $items)
{
    #
    # Suppress error messages
    #
    trap { Write-Output "Error trapped"; continue; }

    #
    # Read raw PDF data
    #
    $pdfText = Get-Content $item -raw

    #
    # Find string (near end of PDF file), if BAD file, ptr will be undefined or 0
    #
    $ptr1 = $pdfText.IndexOf("CreationDate")
    $ptr2 = $pdfText.IndexOf("ModDate")

    #
    # Grab raw dates from file - will ERR if ptr is 0
    #
    try { $cDate = $pdfText.SubString($ptr1, 37); $mDate = $pdfText.SubString($ptr2, 31); }

    #
    # Append filename and bad status to logfile and increment a counter
    # catch block is also where you would rename, move, or delete bad files.
    #
    catch { "*** $item is Broken ***" >> $logFile; $badCounter += 1; continue; }

    #
    # Append filename and good status to logfile
    #
    Write-Output "$item - OK" -EA "Stop" >> $logFile

    #
    # Increment a counter
    #
    $goodCounter += 1
}
#
# Calculate total
#
$totalCounter = $badCounter + $goodCounter

#
# Append 3 blank lines to end of logfile
#
1..3 | %{ Write-Output "" >> $logFile }

#
# Append statistics to end of logfile
#
Write-Output "Total: $totalCounter / BAD: $badCounter / GOOD: $goodCounter" >> $logFile
Write-Output "DONE!`n`n"
n0nuf
fuente
3

Siguiendo los pasos de @ n0nuf, escribí un script por lotes para verificar todos los archivos PDF en una carpeta específica con pdfinfo y empujarlo a través de cpdf si se rompe como un intento de corregirlos:

@ECHO OFF
FOR %%f in (*.PDF) DO (
    echo %%f
    pdfinfo "%%f" 2>&1 | findstr /I "error"  >nul 2>&1
    if not errorlevel 1 (
        echo "bad -> try to fix"
        @cpdf -i %%f -o %%f_.pdf 2>NUL
        mv %%f .\\bak\\%%f
    ) else (
       REM echo good        
    )
)
@ECHO ON

O lo mismo que el script bash:

for file in $(find . -iname "*.pdf")
do
    echo "$file"
    pdfinfo "$file" 2>&1 | grep -i 'error' &> /dev/null
    if [ $? == 0 ]; then
       echo "broken -> try to fix"
       cpdf -i "$file" -o "$file"_.pdf
    fi
done

Los PDF rotos se moverán a una subcarpeta \ bak y los PDF recreados obtienen el sufijo _.pdf (que no es perfecto, pero es lo suficientemente bueno para mí). NOTA: Un PDF recreado contiene errores menores y debería poder verse con un visor de PDF normal. Pero esto no significa que recuperes todo tu contenido. El contenido irrecuperable conduce a páginas vacías.

También probé lo mismo con JHOVE (herramienta de identificación, validación y caracterización de formatos de archivo de código abierto) como lo sugiere @kraftydevil aquí: compruebe si los archivos PDF están dañados usando la línea de comandos en Linux y ahora puede confirmar que este también es un enfoque válido. (Primero tuve menos éxito. Pero luego noté que no había manejado la salida de JHOVE correctamente).

Para probar ambos enfoques, eliminé y modifiqué partes aleatorias de un PDF con un editor de texto (eliminé las secuencias, por lo que las páginas no se pudieron procesar en mi visor de PDF, modifiqué las etiquetas PDF y cambié algunos bits). El resultado es: pdfinfo y JHOVE pueden detectar archivos dañados correctamente (JHOVE fue aún más sensible en algunos casos).

Y aquí está el script equivalente para JHOVE:

@ECHO OFF
FOR %%f in (*.PDF) DO (
    echo %%f
    "C:\Program Files (x86)\JHOVE\jhove.bat" -m pdf-hul %%f | findstr /C:"Well-Formed and valid" >nul 2>&1
    if not errorlevel 1 (
        echo good
    ) else (
        echo "bad -> try to fix"
        @cpdf -i %%f -o %%f_.pdf 2>NUL
        REM mv %%f .\\bak\\%%f
    )
)
@ECHO ON
wp78de
fuente
1
Para su información, recorrer la salida de find es una mala práctica
Scott
Gracias @Scott. El lote FOR-loop de Windows es mucho más seguro, supongo. Le di a la implementación del script bash solo como una muestra.
wp78de
Parece que también es el camino a seguir para Linux: stackoverflow.com/a/9612232/8291949
wp78de