Validar / verificar a integridade dos arquivos PDF

11

Existe alguma ferramenta que eu possa executar nos arquivos PDF (todos os diretórios) e, finalmente, ela lista / identifica os PDFs corrompidos / inválidos?

Tenho centenas de arquivos PDF (relacionados à documentação etc.) no meu computador (máquina Windows) e, muitas vezes, recebo / tenho que enviar dezenas de PDFs por email. Agora é uma rotina normal que o PDF que recebo ou envio esteja corrompido. Às vezes, isso cria sérios problemas quando o arquivo de origem (por exemplo, o arquivo do Word ou o arquivo Tex está ausente / não está disponível instantaneamente).

A verificação desses milhares de PDFs não é possível em tempo limitado, por isso procurei uma ferramenta que possa ser executada uma vez, que digitaliza todos os PDFs (em diretórios e subdiretórios) e, por fim, obtenho uma lista dos arquivos que devo repor. -crio. Até agora, parece que não existe essa ferramenta.

Almirante
fonte
2
Se você estiver no Linux, tente o pdfinfo. Dê uma olhada em: superuser.com/questions/580887/…
marcwho

Respostas:

6

É muito fácil verificar se um arquivo PDF é válido usando o PDFtk. Uma GUI gratuita para PDFtk está disponível no PDF Labs . Ao executar esta ferramenta, você pode carregar quantos PDFs desejar, de vários diretórios (usando o botão Adicionar arquivos) e, em seguida, começará a acessar as páginas desses arquivos PDF muito rapidamente.

Se algum arquivo entre os PDFs selecionados não for um PDF válido, esse utilitário mostrará uma mensagem sobre o erro e o removerá automaticamente da janela de seleção.

Portanto, você pode economizar muitas horas usando este procedimento com o PDFtk. Além disso, se você tiver CPU multicore, poderá executar várias instâncias desse utilitário e lançar centenas de PDFs em cada instância.

Estou usando este software desde o último ano e é a ferramenta PDF mais útil que já usei.

Mubeen Shahid
fonte
2
Alternativamente, usando a ferramenta (pdfinfo.exe) disponível no link mencionado por marcwho, você pode cdem FolderContainingPDFse executar comando a seguir no Shell do Windows, e vai marcar o arquivo inválido PDF em um arquivo de log: 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

Eu usei "pdfinfo.exe" do pacote xpdfbin-win e cpdf.exe para verificar a corrupção de arquivos PDF, mas não queria envolver um binário, se não fosse necessário.

Li que os formatos PDF mais recentes têm um catálogo de dados xml legíveis no final, então abri o PDF com janelas regulares NOTEPAD.exe e rolei os dados ilegíveis até o final e vi várias teclas legíveis. Eu só precisava de uma chave, mas optei por usar CreationDate e ModDate.

O seguinte script do Powershell (PS) verificará TODOS os arquivos PDF no diretório atual e emitirá o status de cada um em um arquivo de texto (! RESULTS.log). Demorou cerca de 2 minutos para executar isso em 35.000 arquivos PDF. Tentei adicionar comentários para quem é novo no PS. Espero que isso economize tempo para alguém. Provavelmente existe uma maneira melhor de fazer isso, mas isso funciona perfeitamente para meus propósitos e lida com erros silenciosamente. Pode ser necessário definir o seguinte no início: $ ErrorActionPreference = "SilentlyContinue" se você encontrar erros na tela.

Copie o seguinte em um arquivo de texto e nomeie-o adequadamente (ex: CheckPDF.ps1) ou abra o PS e navegue até o diretório que contém os arquivos PDF para verificar e colar no console.

#
# 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
fonte
3

Seguindo os passos do @ n0nuf, escrevi um script em lote para verificar todos os PDFs em uma pasta específica com pdfinfo e enviá-lo através do cpdf, se quebrado, como uma tentativa de corrigi-los:

@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

Ou o mesmo que o 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

PDFs quebrados serão movidos para uma subpasta \ bak e os PDFs recriados receberão o sufixo _.pdf (que não é perfeito, mas é bom o suficiente para mim). NOTA: Um PDF recriado contém erros menores e deve ser visualizado com um visualizador de PDF comum. Mas isso não significa que você recupere todo o seu conteúdo. Conteúdo irrecuperável leva a páginas vazias.

Eu também tentei o mesmo com o JHOVE (ferramenta de identificação, validação e caracterização de formato de arquivo de código aberto), conforme sugerido por @kraftydevil aqui: Verifique se os arquivos PDF estão corrompidos usando a linha de comando no Linux e agora posso confirmar que essa também é uma abordagem válida. (Primeiro, tive menos sucesso. Mas depois notei que não havia manipulado a saída do JHOVE corretamente.)

Para testar as duas abordagens, apaguei e alterei partes aleatórias de um PDF com um editor de texto (fluxos removidos, para que as páginas não fossem renderizadas no visualizador de PDF, alterei as Tags PDF e alterei alguns bits). O resultado é: Tanto o pdfinfo quanto o JHOVE conseguem detectar arquivos danificados corretamente (o JHOVE foi ainda mais sensível em alguns casos).

E aqui está o 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
fonte
Obrigado @ Scott. O loop FOR do lote do Windows é muito mais salvo, eu acho. Eu dei a implementação do script bash apenas como uma amostra.
Wp78de
Para parece ser o caminho a percorrer para Linux também: stackoverflow.com/a/9612232/8291949
wp78de