Sprawdź / zweryfikuj integralność plików PDF

11

Czy jest jakieś narzędzie, które mogę uruchomić w archiwach plików PDF (wszystkie katalogi) i wreszcie wyświetla / identyfikuje uszkodzone / nieprawidłowe pliki PDF?

Mam setki plików PDF (związanych z dokumentacją itp.) Na moim komputerze (maszynie z systemem Windows) i bardzo często otrzymuję / muszę wysyłać dziesiątki plików PDF pocztą elektroniczną. Jest to teraz normalna procedura, że ​​plik PDF, który odbieram lub wysyłam, jest uszkodzony. Stwarza to czasem poważne problemy, gdy plik źródłowy (np. Plik Word lub plik Tex brakuje / nie jest natychmiast dostępny).

Sprawdzanie tych tysięcy plików PDF nie jest możliwe w ograniczonym czasie, więc szukałem narzędzia, które mogę uruchomić raz i skanuje wszystkie pliki PDF (w katalogach i podkatalogach), a na koniec otrzymuję listę plików, które powinienem ponownie -Stwórz. Do tej pory wydaje się, że nie ma takiego narzędzia.

Admirał
źródło
2
Jeśli korzystasz z systemu Linux, wypróbuj pdfinfo. Spójrz na: superuser.com/questions/580887/…
marcwho

Odpowiedzi:

6

Za pomocą PDFtk można łatwo sprawdzić, czy plik PDF jest prawidłowy. Wolne GUI dla pdftk jest dostępny w formacie PDF Labs . Po uruchomieniu tego narzędzia można załadować dowolną liczbę plików PDF z wielu katalogów (za pomocą przycisku Dodaj pliki), a następnie bardzo szybko zacznie uzyskiwać dostęp do stron w tych plikach PDF.

Jeśli dowolny plik spośród wybranych plików PDF nie jest prawidłowym plikiem PDF, to narzędzie wyświetli komunikat o błędzie i automatycznie usunie go z okna wyboru.

Dzięki temu możesz zaoszczędzić wiele godzin, stosując tę ​​procedurę z PDFtk. Ponadto, jeśli masz procesor wielordzeniowy, możesz uruchomić wiele instancji tego narzędzia i wrzucić do nich setki plików PDF.

Używam tego oprogramowania od ostatniego roku i jest to najbardziej poręczne narzędzie PDF, z jakiego kiedykolwiek korzystałem.

Mubeen Shahid
źródło
2
Alternatywnie, przy użyciu narzędzia (pdfinfo.exe) dostępny z linkiem wspomnianym przez marcwho, można cdsię FolderContainingPDFsi uruchom następujące polecenie w powłoce systemu Windows, a będzie to oznaczać nieprawidłową plik PDF w pliku dziennika: 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

Użyłem programu „pdfinfo.exe” z pakietu xpdfbin-win i cpdf.exe, aby sprawdzić pliki PDF pod kątem uszkodzeń, ale nie chciałem angażować pliku binarnego, jeśli nie było to konieczne.

Przeczytałem, że nowsze formaty PDF mają na końcu czytelny katalog danych xml, więc otworzyłem plik PDF w zwykłym systemie Windows NOTEPAD.exe i przewinąłem w dół obok nieczytelnych danych do końca i zobaczyłem kilka czytelnych kluczy. Potrzebowałem tylko jednego klucza, ale zdecydowałem się użyć zarówno CreationDate, jak i ModDate.

Poniższy skrypt Powershell (PS) sprawdzi WSZYSTKIE pliki PDF w bieżącym katalogu i wyśle ​​status każdego z nich do pliku tekstowego (! RESULTS.log). Uruchomienie tego z 35 000 plików PDF zajęło około 2 minut. Próbowałem dodać komentarze dla tych, którzy są nowi w PS. Mam nadzieję, że to komuś oszczędza trochę czasu. Jest prawdopodobnie lepszy sposób, aby to zrobić, ale działa to bezbłędnie dla moich celów i cicho obsługuje błędy. Może być konieczne zdefiniowanie na początku: $ ErrorActionPreference = „SilentlyContinue”, jeśli na ekranie pojawią się błędy.

Skopiuj następujące elementy do pliku tekstowego i nadaj mu odpowiednią nazwę (np. CheckPDF.ps1) lub otwórz PS i przejdź do katalogu zawierającego pliki PDF, aby sprawdzić i wkleić go w konsoli.

#
# 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
źródło
3

Podążając śladami @ n0nuf, napisałem skrypt wsadowy, aby sprawdzić wszystkie pliki PDF w określonym folderze za pomocą pdfinfo i przepchnąć go przez cpdf, jeśli jest uszkodzony, próbując je naprawić:

@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

Lub to samo co skrypt 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

Zepsute pliki PDF zostaną przeniesione do podfolderu \ bak, a odtworzone pliki PDF otrzymają przyrostek _.pdf (co nie jest idealne, ale dla mnie wystarczające). UWAGA: Odtworzony plik PDF zawiera mniej błędów i powinien być widoczny w zwykłej przeglądarce plików PDF. Ale to nie znaczy, że odzyskujesz wszystkie treści. Nieodwracalna zawartość prowadzi do pustych stron.

Próbowałem również tego samego z JHOVE (narzędzie do identyfikacji, sprawdzania poprawności i charakteryzowania formatu plików Open Source), jak sugeruje @kraftydevil tutaj: Sprawdź, czy pliki PDF są uszkodzone za pomocą wiersza poleceń w systemie Linux i teraz mogę potwierdzić, że jest to również poprawne podejście. (Najpierw odniosłem mniejszy sukces. Ale potem zauważyłem, że nie obsłużyłem poprawnie wyjścia JHOVE.)

Aby przetestować oba podejścia, usunąłem i zmieniłem losowe części z pliku PDF za pomocą edytora tekstu (usunąłem strumienie, więc strony nie renderowały się w mojej przeglądarce PDF, zmieniły tagi PDF i przesunąłem niektóre bity). Rezultat jest następujący: Zarówno pdfinfo, jak i JHOVE są w stanie poprawnie wykryć uszkodzone pliki (w niektórych przypadkach JHOVE był jeszcze bardziej wrażliwy).

A oto skrypt równoważny dla 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
źródło
Dziękuję @Scott. Wydaje mi się, że wsadowa pętla FOR systemu Windows jest znacznie bardziej oszczędna. Jako przykład podałem implementację skryptu bash.
wp78de
Wydaje się, że jest to również droga do Linuksa: stackoverflow.com/a/9612232/8291949
wp78de