<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://onnocenter.or.id/wiki/index.php?action=history&amp;feed=atom&amp;title=Batch_pdf_to_md.sh</id>
	<title>Batch pdf to md.sh - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://onnocenter.or.id/wiki/index.php?action=history&amp;feed=atom&amp;title=Batch_pdf_to_md.sh"/>
	<link rel="alternate" type="text/html" href="https://onnocenter.or.id/wiki/index.php?title=Batch_pdf_to_md.sh&amp;action=history"/>
	<updated>2026-07-27T05:40:18Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.4</generator>
	<entry>
		<id>https://onnocenter.or.id/wiki/index.php?title=Batch_pdf_to_md.sh&amp;diff=73720&amp;oldid=prev</id>
		<title>Onnowpurbo: Created page with &quot;&lt;pre&gt;  #!/usr/bin/env bash # Batch wrapper untuk pdf_to_rag_md.py # # Penggunaan: #   ./batch_pdf_to_md.sh /path/folder_pdf #   ./batch_pdf_to_md.sh /path/folder_pdf /path/fol...&quot;</title>
		<link rel="alternate" type="text/html" href="https://onnocenter.or.id/wiki/index.php?title=Batch_pdf_to_md.sh&amp;diff=73720&amp;oldid=prev"/>
		<updated>2026-07-26T01:47:44Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&amp;lt;pre&amp;gt;  #!/usr/bin/env bash # Batch wrapper untuk pdf_to_rag_md.py # # Penggunaan: #   ./batch_pdf_to_md.sh /path/folder_pdf #   ./batch_pdf_to_md.sh /path/folder_pdf /path/fol...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# Batch wrapper untuk pdf_to_rag_md.py&lt;br /&gt;
#&lt;br /&gt;
# Penggunaan:&lt;br /&gt;
#   ./batch_pdf_to_md.sh /path/folder_pdf&lt;br /&gt;
#   ./batch_pdf_to_md.sh /path/folder_pdf /path/folder_output&lt;br /&gt;
#   ./batch_pdf_to_md.sh /path/folder_pdf /path/folder_output /path/pdf_to_rag_md.py&lt;br /&gt;
#&lt;br /&gt;
# Hasil:&lt;br /&gt;
#   OUTPUT_DIR/&amp;lt;path-relatif&amp;gt;/&amp;lt;nama-pdf&amp;gt;/&lt;br /&gt;
#       ├── *.md&lt;br /&gt;
#       └── manifest.json&lt;br /&gt;
&lt;br /&gt;
set -Eeuo pipefail&lt;br /&gt;
IFS=$'\n\t'&lt;br /&gt;
&lt;br /&gt;
PROGRAM_NAME=&amp;quot;$(basename &amp;quot;$0&amp;quot;)&amp;quot;&lt;br /&gt;
SCRIPT_DIR=&amp;quot;$(cd -- &amp;quot;$(dirname -- &amp;quot;${BASH_SOURCE[0]}&amp;quot;)&amp;quot; &amp;amp;&amp;amp; pwd -P)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
usage() {&lt;br /&gt;
    cat &amp;lt;&amp;lt;EOF&lt;br /&gt;
Penggunaan:&lt;br /&gt;
  $PROGRAM_NAME INPUT_PATH [OUTPUT_DIR] [PYTHON_SCRIPT]&lt;br /&gt;
&lt;br /&gt;
Argumen:&lt;br /&gt;
  INPUT_PATH      Folder yang akan dicari secara rekursif, atau satu file PDF.&lt;br /&gt;
  OUTPUT_DIR      Folder induk hasil konversi.&lt;br /&gt;
                  Default: INPUT_PATH/output untuk input folder,&lt;br /&gt;
                  atau folder_file/output untuk input satu PDF.&lt;br /&gt;
  PYTHON_SCRIPT   Lokasi script Python konverter.&lt;br /&gt;
                  Default: dicari di folder yang sama dengan shell script.&lt;br /&gt;
&lt;br /&gt;
Contoh:&lt;br /&gt;
  $PROGRAM_NAME /opt/ai-stack/documents&lt;br /&gt;
  $PROGRAM_NAME /opt/ai-stack/documents /opt/ai-stack/output&lt;br /&gt;
  $PROGRAM_NAME ./pdf ./output ./pdf_to_rag_md.py&lt;br /&gt;
EOF&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
log() {&lt;br /&gt;
    printf '[%s] %s\n' &amp;quot;$(date '+%Y-%m-%d %H:%M:%S')&amp;quot; &amp;quot;$*&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
fail() {&lt;br /&gt;
    printf 'ERROR: %s\n' &amp;quot;$*&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
    exit 1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if [[ ${1:-} == &amp;quot;-h&amp;quot; || ${1:-} == &amp;quot;--help&amp;quot; ]]; then&lt;br /&gt;
    usage&lt;br /&gt;
    exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
[[ $# -ge 1 &amp;amp;&amp;amp; $# -le 3 ]] || {&lt;br /&gt;
    usage &amp;gt;&amp;amp;2&lt;br /&gt;
    exit 2&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
command -v python3 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || fail &amp;quot;python3 tidak ditemukan.&amp;quot;&lt;br /&gt;
command -v find &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || fail &amp;quot;Perintah find tidak ditemukan.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
INPUT_PATH=&amp;quot;$1&amp;quot;&lt;br /&gt;
[[ -e &amp;quot;$INPUT_PATH&amp;quot; ]] || fail &amp;quot;Path input tidak ditemukan: $INPUT_PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Ubah menjadi absolute path tanpa membutuhkan realpath.&lt;br /&gt;
if [[ -d &amp;quot;$INPUT_PATH&amp;quot; ]]; then&lt;br /&gt;
    INPUT_PATH=&amp;quot;$(cd -- &amp;quot;$INPUT_PATH&amp;quot; &amp;amp;&amp;amp; pwd -P)&amp;quot;&lt;br /&gt;
    INPUT_IS_DIR=1&lt;br /&gt;
else&lt;br /&gt;
    INPUT_DIR=&amp;quot;$(cd -- &amp;quot;$(dirname -- &amp;quot;$INPUT_PATH&amp;quot;)&amp;quot; &amp;amp;&amp;amp; pwd -P)&amp;quot;&lt;br /&gt;
    INPUT_PATH=&amp;quot;$INPUT_DIR/$(basename -- &amp;quot;$INPUT_PATH&amp;quot;)&amp;quot;&lt;br /&gt;
    INPUT_IS_DIR=0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [[ $# -ge 2 ]]; then&lt;br /&gt;
    OUTPUT_DIR=&amp;quot;$2&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
    if (( INPUT_IS_DIR )); then&lt;br /&gt;
        OUTPUT_DIR=&amp;quot;$INPUT_PATH/output&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        OUTPUT_DIR=&amp;quot;$(dirname -- &amp;quot;$INPUT_PATH&amp;quot;)/output&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
fi&lt;br /&gt;
mkdir -p -- &amp;quot;$OUTPUT_DIR&amp;quot;&lt;br /&gt;
OUTPUT_DIR=&amp;quot;$(cd -- &amp;quot;$OUTPUT_DIR&amp;quot; &amp;amp;&amp;amp; pwd -P)&amp;quot;&lt;br /&gt;
[[ &amp;quot;$OUTPUT_DIR&amp;quot; != &amp;quot;$INPUT_PATH&amp;quot; ]] \&lt;br /&gt;
    || fail &amp;quot;OUTPUT_DIR tidak boleh sama persis dengan folder input. Gunakan subfolder, misalnya: $INPUT_PATH/output&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [[ $# -ge 3 ]]; then&lt;br /&gt;
    PYTHON_SCRIPT=&amp;quot;$3&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
    if [[ -f &amp;quot;$SCRIPT_DIR/pdf_to_rag_md.py&amp;quot; ]]; then&lt;br /&gt;
        PYTHON_SCRIPT=&amp;quot;$SCRIPT_DIR/pdf_to_rag_md.py&amp;quot;&lt;br /&gt;
    elif [[ -f &amp;quot;$SCRIPT_DIR/pdf_to_rag_md(2).py&amp;quot; ]]; then&lt;br /&gt;
        PYTHON_SCRIPT=&amp;quot;$SCRIPT_DIR/pdf_to_rag_md(2).py&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        fail &amp;quot;Script Python tidak ditemukan. Letakkan pdf_to_rag_md.py di $SCRIPT_DIR atau berikan argumen PYTHON_SCRIPT.&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
[[ -f &amp;quot;$PYTHON_SCRIPT&amp;quot; ]] || fail &amp;quot;Script Python tidak ditemukan: $PYTHON_SCRIPT&amp;quot;&lt;br /&gt;
PYTHON_SCRIPT=&amp;quot;$(cd -- &amp;quot;$(dirname -- &amp;quot;$PYTHON_SCRIPT&amp;quot;)&amp;quot; &amp;amp;&amp;amp; pwd -P)/$(basename -- &amp;quot;$PYTHON_SCRIPT&amp;quot;)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Pastikan script Python valid dan dependensinya tersedia sebelum batch dimulai.&lt;br /&gt;
python3 -m py_compile &amp;quot;$PYTHON_SCRIPT&amp;quot; \&lt;br /&gt;
    || fail &amp;quot;Script Python gagal diperiksa dengan py_compile.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
python3 - &amp;lt;&amp;lt;'PY' \&lt;br /&gt;
    || fail &amp;quot;Dependensi Python belum lengkap. Instal dengan: python3 -m pip install pymupdf pyyaml&amp;quot;&lt;br /&gt;
try:&lt;br /&gt;
    import pymupdf  # noqa: F401&lt;br /&gt;
except ImportError:&lt;br /&gt;
    import fitz  # noqa: F401&lt;br /&gt;
import yaml  # noqa: F401&lt;br /&gt;
PY&lt;br /&gt;
&lt;br /&gt;
find_input_files() {&lt;br /&gt;
    if [[ &amp;quot;$OUTPUT_DIR&amp;quot; == &amp;quot;$INPUT_PATH/&amp;quot;* ]]; then&lt;br /&gt;
        find &amp;quot;$INPUT_PATH&amp;quot; -path &amp;quot;$OUTPUT_DIR&amp;quot; -prune -o -type f &amp;quot;$@&amp;quot; -print0&lt;br /&gt;
    else&lt;br /&gt;
        find &amp;quot;$INPUT_PATH&amp;quot; -type f &amp;quot;$@&amp;quot; -print0&lt;br /&gt;
    fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
printf '\n=== Daftar semua file pada input ===\n'&lt;br /&gt;
if (( INPUT_IS_DIR )); then&lt;br /&gt;
    while IFS= read -r -d '' file; do&lt;br /&gt;
        printf '%s\n' &amp;quot;$file&amp;quot;&lt;br /&gt;
    done &amp;lt; &amp;lt;(find_input_files | sort -z)&lt;br /&gt;
else&lt;br /&gt;
    printf '%s\n' &amp;quot;$INPUT_PATH&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
printf '=== Akhir daftar file ===\n\n'&lt;br /&gt;
&lt;br /&gt;
PDF_FILES=()&lt;br /&gt;
if (( INPUT_IS_DIR )); then&lt;br /&gt;
    while IFS= read -r -d '' pdf; do&lt;br /&gt;
        PDF_FILES+=(&amp;quot;$pdf&amp;quot;)&lt;br /&gt;
    done &amp;lt; &amp;lt;(find_input_files -iname '*.pdf' | sort -z)&lt;br /&gt;
else&lt;br /&gt;
    [[ &amp;quot;${INPUT_PATH,,}&amp;quot; == *.pdf ]] \&lt;br /&gt;
        || fail &amp;quot;File input bukan PDF: $INPUT_PATH&amp;quot;&lt;br /&gt;
    PDF_FILES+=(&amp;quot;$INPUT_PATH&amp;quot;)&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
TOTAL=${#PDF_FILES[@]}&lt;br /&gt;
if (( TOTAL == 0 )); then&lt;br /&gt;
    log &amp;quot;Tidak ada file PDF yang ditemukan.&amp;quot;&lt;br /&gt;
    exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LOG_FILE=&amp;quot;$OUTPUT_DIR/batch_conversion.log&amp;quot;&lt;br /&gt;
SUMMARY_FILE=&amp;quot;$OUTPUT_DIR/batch_summary.tsv&amp;quot;&lt;br /&gt;
printf 'status\tinput_pdf\toutput_folder\n' &amp;gt; &amp;quot;$SUMMARY_FILE&amp;quot;&lt;br /&gt;
: &amp;gt; &amp;quot;$LOG_FILE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
log &amp;quot;Ditemukan $TOTAL file PDF.&amp;quot;&lt;br /&gt;
log &amp;quot;Output utama: $OUTPUT_DIR&amp;quot;&lt;br /&gt;
log &amp;quot;Log batch: $LOG_FILE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
SUCCESS=0&lt;br /&gt;
FAILED=0&lt;br /&gt;
INDEX=0&lt;br /&gt;
&lt;br /&gt;
for PDF_FILE in &amp;quot;${PDF_FILES[@]}&amp;quot;; do&lt;br /&gt;
    ((INDEX += 1))&lt;br /&gt;
&lt;br /&gt;
    if (( INPUT_IS_DIR )); then&lt;br /&gt;
        RELATIVE_PATH=&amp;quot;${PDF_FILE#&amp;quot;$INPUT_PATH&amp;quot;/}&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        RELATIVE_PATH=&amp;quot;$(basename -- &amp;quot;$PDF_FILE&amp;quot;)&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    RELATIVE_PARENT=&amp;quot;$(dirname -- &amp;quot;$RELATIVE_PATH&amp;quot;)&amp;quot;&lt;br /&gt;
    PDF_NAME=&amp;quot;$(basename -- &amp;quot;$RELATIVE_PATH&amp;quot;)&amp;quot;&lt;br /&gt;
    PDF_STEM=&amp;quot;${PDF_NAME%.*}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    if [[ &amp;quot;$RELATIVE_PARENT&amp;quot; == &amp;quot;.&amp;quot; ]]; then&lt;br /&gt;
        PDF_OUTPUT_DIR=&amp;quot;$OUTPUT_DIR/$PDF_STEM&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        PDF_OUTPUT_DIR=&amp;quot;$OUTPUT_DIR/$RELATIVE_PARENT/$PDF_STEM&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    mkdir -p -- &amp;quot;$PDF_OUTPUT_DIR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    printf '\n[%d/%d] Konversi: %s\n' &amp;quot;$INDEX&amp;quot; &amp;quot;$TOTAL&amp;quot; &amp;quot;$PDF_FILE&amp;quot;&lt;br /&gt;
    printf '        Output   : %s\n' &amp;quot;$PDF_OUTPUT_DIR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    printf '\n===== [%d/%d] %s =====\n' &amp;quot;$INDEX&amp;quot; &amp;quot;$TOTAL&amp;quot; &amp;quot;$PDF_FILE&amp;quot; \&lt;br /&gt;
        | tee -a &amp;quot;$LOG_FILE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    set +e&lt;br /&gt;
    python3 &amp;quot;$PYTHON_SCRIPT&amp;quot; \&lt;br /&gt;
        &amp;quot;$PDF_FILE&amp;quot; \&lt;br /&gt;
        --output-dir &amp;quot;$PDF_OUTPUT_DIR&amp;quot; \&lt;br /&gt;
        --overwrite 2&amp;gt;&amp;amp;1 | tee -a &amp;quot;$LOG_FILE&amp;quot;&lt;br /&gt;
    EXIT_CODE=${PIPESTATUS[0]}&lt;br /&gt;
    set -e&lt;br /&gt;
&lt;br /&gt;
    if (( EXIT_CODE == 0 )); then&lt;br /&gt;
        printf 'SUCCESS\t%s\t%s\n' &amp;quot;$PDF_FILE&amp;quot; &amp;quot;$PDF_OUTPUT_DIR&amp;quot; \&lt;br /&gt;
            &amp;gt;&amp;gt; &amp;quot;$SUMMARY_FILE&amp;quot;&lt;br /&gt;
        ((SUCCESS += 1))&lt;br /&gt;
        log &amp;quot;BERHASIL: $PDF_FILE&amp;quot; | tee -a &amp;quot;$LOG_FILE&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        printf 'FAILED(%d)\t%s\t%s\n' &amp;quot;$EXIT_CODE&amp;quot; &amp;quot;$PDF_FILE&amp;quot; &amp;quot;$PDF_OUTPUT_DIR&amp;quot; \&lt;br /&gt;
            &amp;gt;&amp;gt; &amp;quot;$SUMMARY_FILE&amp;quot;&lt;br /&gt;
        ((FAILED += 1))&lt;br /&gt;
        log &amp;quot;GAGAL (exit $EXIT_CODE): $PDF_FILE&amp;quot; | tee -a &amp;quot;$LOG_FILE&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
printf '\n=== Ringkasan batch ===\n'&lt;br /&gt;
printf 'Total PDF : %d\n' &amp;quot;$TOTAL&amp;quot;&lt;br /&gt;
printf 'Berhasil  : %d\n' &amp;quot;$SUCCESS&amp;quot;&lt;br /&gt;
printf 'Gagal     : %d\n' &amp;quot;$FAILED&amp;quot;&lt;br /&gt;
printf 'Output    : %s\n' &amp;quot;$OUTPUT_DIR&amp;quot;&lt;br /&gt;
printf 'Ringkasan : %s\n' &amp;quot;$SUMMARY_FILE&amp;quot;&lt;br /&gt;
printf 'Log       : %s\n' &amp;quot;$LOG_FILE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(( FAILED == 0 ))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Onnowpurbo</name></author>
	</entry>
</feed>