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


11

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

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

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


2
Linuxを使用している場合は、pdfinfoを試してください。見てみましょう:superuser.com/questions/580887/...
marcwho


回答:


6

PDFtkを使用すると、PDFファイルが有効かどうかを簡単に確認できます。PDFtkのための無料のGUIは、から入手可能であるPDF研究所。このツールを実行すると、複数のディレクトリから([ファイルの追加]ボタンを使用して)必要な数のPDFを読み込むことができ、これらのPDFファイル内のページへのアクセスがすぐに開始されます。

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

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

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


2
また、marcwhoによって言及リンクから入手可能(pdfinfo.exe)、あなたができるツールを使用してcdFolderContainingPDFsし、Windowsのシェルで次のコマンドを実行し、ログファイルに無効な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パッケージの「pdfinfo.exe」とcpdf.exeを使用してPDFファイルの破損をチェックしましたが、不要な場合はバイナリを使用したくありませんでした。

新しいPDF形式には最後に読み取り可能なxmlデータカタログがあることを読んだので、通常のウィンドウNOTEPAD.exeでPDFを開き、読み取り不可能なデータを最後までスクロールして、いくつかの読み取り可能なキーを見ました。必要なキーは1つだけですが、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の足跡をたどって、特定のフォルダー内のすべてのPDFをpdfinfoでチェックし、壊れている場合は修正する試みとして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 2017

:あまりにもLinux用の進むべき道であると考えられるためstackoverflow.com/a/9612232/8291949
wp78de
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.