web-dev-qa-db-ja.com

検証/検証PDFファイルの整合性

PDFアーカイブ(すべてのディレクトリ)で実行できるツールはありますか?最後に、破損したPDFまたは無効なPDFをリスト/識別しますか?

私のコンピューター(Windowsマシン)には数百のPDFファイル(ドキュメントなどに関連する))があり、非常に多くの場合、数十のPDFを電子メールで送受信する必要があります。 PDF受信または送信するルーチンが破損しています。これにより、ソースファイル(WordファイルやTexファイルが見つからない/すぐに利用できないなど)の場合に深刻な問題が発生することがあります。

これらの何千ものPDFをチェックすることは有限の時間では不可能なので、私は一度実行できるツールを検索し、それはすべてのPDF(ディレクトリおよびサブディレクトリ内)をスキャンし、最後に再実行する必要のあるファイルのリストを取得します-作成。今のところ、そのようなツールはないようです。

11
Admiral

PDFtkを使用すると、PDFファイルが有効かどうかを簡単に確認できます。 PDFtkの無料GUIPDF Labs から入手できます。このツールを実行すると、複数のディレクトリから([ファイルの追加]ボタンを使用して)必要な数のPDFをロードでき、これらのPDFファイル内のページへのアクセスが非常に速くなります。

選択したPDFのいずれかのファイルが有効なPDFではない場合、このユーティリティはエラーに関するメッセージを表示し、選択ウィンドウから自動的に削除します。

したがって、PDFtkでこの手順を使用すると、多くの時間を節約できます。さらに、マルチコアCPUを使用している場合は、このユーティリティの複数のインスタンスを実行して、各インスタンスに数百のPDFを投入できます。

私はこのソフトウェアを過去1年以来使用しており、これは今まで使用した中で最も便利なPDFツールです。

6
Mubeen Shahid

Xpdfbin-winパッケージの "pdfinfo.exe"とcpdf.exeを使用してPDFファイルの破損を確認しましたが、不要な場合はバイナリを使用したくありませんでした。

新しいPDF形式には最後に読み取り可能なxmlデータカタログがあるため、通常のウィンドウでNOTEPAD.exeを使用してPDFを開き、下にスクロールして最後まで判読できないデータがあり、いくつかの判読可能なキーがありましたが、必要なキーは1つだけでしたが、CreationDateとModDateの両方を使用することにしました。

次のPowershell(PS)スクリプトは、現在のディレクトリのすべてのPDF=ファイルをチェックし、それぞれのステータスをテキストファイル(!RESULTS.log)に出力します。実行に約2分かかりましたこれは35,000に対してPDFファイルです。私は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"
4
n0nuf

@ 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
3
wp78de