验证/验证PDF文件的完整性


11

有什么我可以在PDF档案(所有目录)上运行的工具,最终它可以列出/标识损坏/无效的PDF?

我的计算机(Windows机器)上有数百个PDF文件(与文档等有关),而且经常收到/必须通过电子邮件发送数十个PDF。现在,我接收或发送的PDF已损坏是正常的例程。当源文件(例如Word文件或Tex文件丢失/无法立即使用)时,有时会造成严重的麻烦。

在有限的时间内不可能检查成千上万的PDF,因此我搜索了一个可以运行一次的工具,它扫描了所有PDF(在目录和子目录中),最后我得到了这些文件的列表, -创建。到目前为止,似乎还没有这样的工具。


2
如果您使用的是Linux,请尝试pdfinfo。看看:superuser.com/questions/580887/...
marcwho


Answers:


6

使用PDFtk可以很容易地检查PDF文件是否有效。一对PDFTK免费GUI可从PDF实验室。运行此工具时,可以从多个目录中加载所需数量的PDF(使用“添加文件”按钮),然后它将开始非常快速地访问这些PDF文件中的页面。

如果所选PDF中的任何文件都不是有效的PDF,则该实用程序将显示有关该错误的消息,并将自动从选择窗口中将其删除。

因此,使用PDFtk使用此过程可以节省许多时间。此外,如果您具有多核CPU,则可以运行此实用程序的多个实例,并在每个实例中放入数百个PDF。

我从去年开始就使用此软件,它是我使用过的最方便的PDF工具。


2
另外,使用工具(pdfinfo.exe)可从marcwho提到的链接,就可以cd进入FolderContainingPDFs,并在Windows shell中运行以下命令,它将标志着一个日志文件无效的PDF文件: 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沙希德

4

我已经使用了xpdfbin-win软件包和cpdf.exe中的“ pdfinfo.exe”来检查PDF文件是否损坏,但是如果没有必要,则不想包含二进制文件。

我了解到,较新的PDF格式的末尾具有可读的xml数据目录,因此我使用常规窗口NOTEPAD.exe打开了PDF,并向下滚动经过了不可读的数据,最后看到了几个可读的键。我只需要一个键,但是选择同时使用CreationDate和ModDate。

以下Powershell(PS)脚本将检查当前目录中的所有PDF文件,并将每个状态输出为文本文件(!RESULTS.log)。对35,000个PDF文件运行了大约2分钟。我试图为PS的新手添加评论。希望这可以节省一些时间。可能有更好的方法来执行此操作,但这对我而言是完美的,并且可以静默处理错误。您可能需要在开始时定义以下内容:$ ErrorActionPreference =“ SilentlyContinue”,如果您在屏幕上看到错误。

将以下内容复制到文本文件中并适当命名(例如:CheckPDF.ps1),或打开PS并浏览到包含PDF文件的目录以进行检查并将其粘贴在控制台中。

#
# 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"

3

遵循@ n0nuf的脚步,我编写了一个批处理脚本,使用pdfinfo检查特定文件夹中的所有PDF,如果损坏则通过cpdf推送它,以尝试修复它们:

@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

或与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

损坏的PDF将移到\ bak子文件夹中,并且重新创建的PDF具有后缀_.pdf(这不是完美的,但对我来说足够好了)。注意:重新创建的PDF包含的错误较少,应该可以用常规的PDF查看器查看。但这并不意味着您可以收回所有内容。无法恢复的内容导致空白页。

我也使用@kraftydevil的建议使用JHOVE(开源文件格式识别,验证和表征工具)进行了相同的尝试:在Linux上使用命令行检查PDF文件是否已损坏,现在可以确认这也是有效的方法。(首先,我获得的成功较少。但是后来,我注意到我没有正确处理JHOVE的输出。)

为了测试这两种方法,我使用文本编辑器从PDF中删除和更改了随机部分(删除了流,因此页面无法在PDF查看器中呈现,更改了PDF标签并移位了一些位)。结果是:pdfinfo和JHOVE都能够正确发现损坏的文件(在某些情况下,JHOVE更加敏感)。

这是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


谢谢@斯科特。Windows批处理FOR循环比我想的要省得多。我以示例的形式给出了bash脚本实现。
wp78de

对于Linux来说似乎也是如此:stackoverflow.com/a/9612232/8291949
wp78de
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.