diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-05-10 22:57:02 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-05-10 22:57:02 +0200 |
| commit | 3cd9138c9d8fb9be248c75330cca9da47f4d2e8a (patch) | |
| tree | b3b677a9c1a474589f45d20953028a987fa73b80 /pdf-txt | |
| parent | 83f7fe4b8402bab171d110703a1b1115efbc9b28 (diff) | |
| download | bin-3cd9138c9d8fb9be248c75330cca9da47f4d2e8a.tar.gz bin-3cd9138c9d8fb9be248c75330cca9da47f4d2e8a.zip | |
added a whole bunch of scripts
Diffstat (limited to 'pdf-txt')
| -rwxr-xr-x | pdf-txt | 80 |
1 files changed, 80 insertions, 0 deletions
@@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# pdf-txt — extract clean text from OCR'd PDFs, recursively +# +# Usage: pdf-txt <path> [<path>...] +# +# <path> can be a .pdf file or a directory (walked recursively). +# For each PDF with a text layer, writes a sibling .txt file using +# pdftotext -layout, with "=== Page N ===" markers inserted. +# Skips PDFs without a text layer. +# Skips PDFs whose .txt is newer than the source. + +set -eu + +die() { printf "ERROR: %s\n" "$*" >&2; exit 1; } +need() { command -v "$1" >/dev/null 2>&1 || die "Missing: $1 (apt install $2)"; } + +need pdftotext poppler-utils +need find findutils +need awk gawk + +processed=0; skipped_no_ocr=0; skipped_existing=0; failed=0 + +extract_one() { + local pdf="$1" + local txt="${pdf%.[Pp][Dd][Ff]}.txt" + + if [ -f "$txt" ] && [ "$txt" -nt "$pdf" ]; then + printf " up-to-date %s\n" "$pdf" + skipped_existing=$((skipped_existing + 1)) + return 0 + fi + + # OCR/text-layer detection: sample first 3 pages + local tmp; tmp=$(mktemp) + pdftotext -l 3 "$pdf" "$tmp" 2>/dev/null || true + local nchars; nchars=$(tr -d '[:space:]' < "$tmp" | wc -c) + rm -f "$tmp" + + if [ "$nchars" -lt 50 ]; then + printf " no OCR %s\n" "$pdf" + skipped_no_ocr=$((skipped_no_ocr + 1)) + return 0 + fi + + if pdftotext -layout "$pdf" - 2>/dev/null | awk ' + BEGIN { page = 1; printf "=== Page %d ===\n\n", page } + /\014/ { page++; printf "\n=== Page %d ===\n\n", page; next } + { print } + ' > "$txt"; then + printf " extracted %s\n" "$txt" + processed=$((processed + 1)) + else + rm -f "$txt" + printf " FAILED %s\n" "$pdf" >&2 + failed=$((failed + 1)) + fi +} + +walk() { + local target="$1" + if [ -f "$target" ]; then + case "$target" in + *.pdf|*.PDF) extract_one "$target" ;; + *) printf " not a PDF %s\n" "$target" >&2 ;; + esac + elif [ -d "$target" ]; then + while IFS= read -r -d '' pdf; do + extract_one "$pdf" + done < <(find "$target" -type f -iname '*.pdf' -print0 | sort -z) + else + printf " not found %s\n" "$target" >&2 + fi +} + +[ $# -ge 1 ] || die "Usage: pdf-txt <path> [<path>...]" + +for arg in "$@"; do walk "$arg"; done + +printf "\nDone. processed=%d no_ocr=%d up_to_date=%d failed=%d\n" \ + "$processed" "$skipped_no_ocr" "$skipped_existing" "$failed" |
