PPDF123
How-to2026-09-2910 menit baca

Memakai pdfx di terminal dan di CI: dari perintah pertama sampai skrip yang andal

Pakai pdfx di baris perintah untuk menggabungkan, mengompres, dan memberi tanda air, memproses banyak berkas sekaligus, dan merangkai alat dalam satu permintaan dengan pipeline. Untuk skrip dan CI, pelajari apa yang bisa diandalkan: kode keluar, laporan --json, input dan output standar, serta mengapa alat filter bersyarat tanpa kecocokan tetap keluar dengan 0.

PDF123 Β· Updated 2026-09-29

Sebelum memasukkan pdfx ke skrip atau integrasi berkelanjutan (CI), ingat dua hal. Kode keluar 0 tidak selalu berarti berkas ditulis: alat filter bersyarat tanpa kecocokan juga keluar dengan 0. Dan --json berbentuk lain untuk satu input dibanding beberapa input, sehingga skrip yang hanya mengurai array files tidak menemukan apa-apa ketika hanya satu berkas yang cocok. pdfx adalah klien HTTP: berkas diunggah ke server untuk diproses, tidak ada mesin lokal, dan tidak ada mode luring. Referensi perintah lengkap ada di panduan CLI di halaman pengembang.

Diagram: satu panggilan pdfx menyerahkan tiga hal kepada skrip, laporan JSON di output standar, pesan kegagalan di error standar, dan kode keluar; skrip membaca kode keluar lebih dulu

Pasang, lalu gabungkan dua berkas

Anda memerlukan Node 20.3 atau lebih baru, atau Bun:

npm install -g @pdf123/cli
pdfx --version

Jika Anda tidak ingin memasang secara global, taruh npx @pdf123/cli di depan perintah. Dengan dua PDF di direktori saat ini:

pdfx merge a.pdf b.pdf -o merged.pdf

Bila berhasil, output standar mencetak merged.pdf. Itu tadi Gabungkan PDF. Sebelum berganti alat, tanyakan bidangnya alih-alih menebak nama parameter:

pdfx describe watermark
Add Watermark (watermark) - Add text or image watermarks to PDF files
Input:    1 file (.pdf)
Result:   file
Fields:
  --watermarkText <value>  Watermark text [default: PDF123]
  --fontSize <number>      Font size [default: 30]
                           min 6, max 200

(Ini kutipan; bidangnya juga mencakup --rotation, --customColor, dan lainnya.) Sebuah bidang hanyalah opsi baris perintah:

pdfx watermark in.pdf --watermarkText DRAFT -o marked.pdf

pdfx list mencantumkan ke-95 alat, --category security hanya mencantumkan satu kategori, dan --query watermark mencari berdasarkan kata.

Beberapa berkas masuk ke satu direktori, dan berkas yang ada tidak ditimpa

Berikan beberapa input ke alat berkas tunggal dan tiap berkas ditulis ke direktori yang disebut -o begitu selesai, tidak ditahan sampai akhir. Jika satu berkas gagal, yang lain tetap berjalan, dan kode keluar di akhir batch adalah 1.

pdfx compress a.pdf b.pdf -o small/

Output standar dari satu kali jalan tampak seperti ini, dan urutannya bisa berbeda setiap kali:

a.pdf -> small/a.pdf
b.pdf -> small/b.pdf

Direktori yang sudah ada berfungsi apa adanya; jika direktorinya belum ada, -o memerlukan / di akhir, kalau tidak small dianggap nama berkas. Tanpa -o, hasil mendarat di direktori saat ini dengan nama yang diberikan server; berkas yang sudah ada tidak ditimpa dan yang baru menjadi a-1.pdf, a-2.pdf. Nama berkas tertentu (-o same.pdf) menggantikan isi yang ada, sesuai permintaan Anda. Secara bawaan dua berkas diproses sekaligus; ubah dengan --concurrency. Jika Anda menekan Ctrl-C di tengah batch, berkas yang sudah ditulis tetap ada dan kode keluarnya 130.

Buka berkas terenkripsi dengan --input-password PASSWORD. Bila batch mencampur berkas terkunci dan tidak terkunci, pakai --password-for FILE=PASSWORD, yang bisa diulang.

Panggil alat satu per satu untuk berkas antara, selain itu pakai pipeline

Untuk menggabungkan, lalu memberi tanda air, lalu mengompres, ketika Anda tidak perlu hasil antara di disk, lipat semuanya menjadi satu permintaan dengan pipeline; berkas antara tidak diunduh dan diunggah lagi. Jika Anda ingin berkas dari tiap langkah, panggil alat satu per satu. Satu pipeline menghasilkan satu berkas.

pdfx pipeline a.pdf b.pdf --step merge --step compress -o merged-small.pdf

# Bila sebuah langkah butuh parameter, uraikan langkah-langkahnya dalam JSON
pdfx pipeline a.pdf b.pdf \
  --steps '[{"tool":"merge"},{"tool":"watermark","params":{"watermarkText":"DRAFT"}},{"tool":"compress"}]' \
  -o out.pdf

Satu pipeline memiliki paling banyak 8 langkah; langkah ke-9 mendapat HTTP 400: at most 8 pipeline steps allowed. Alat yang membutuhkan berkas kedua (misalnya overlay-pdfs, yang menumpuk PDF lain) tidak bisa menjadi langkah pipeline. pdfx menolaknya sebelum mengunggah, dengan kode keluar 2 dan pesan Tool "overlay-pdfs" needs a second file and cannot run as a pipeline step.

Pakai input standar hanya bila Anda ingin menyambungkan perintah ke pipe. Argumen berkas - membaca dari input standar, dan -o - menulis hasil ke output standar:

cat report.pdf | pdfx compress - -o - > report-small.pdf

Dalam mode ini output standar hanya membawa byte berkas; pesan dan galat masuk ke error standar, jadi pengalihan aman dilakukan. Kami memeriksanya dengan PDF sekitar 1 KB: output standar berisi PDF sebesar 1040 byte, sama besar dengan berkas yang ditulis dengan -o, dan error standar kosong. Bila Anda membaca dari input standar dan tidak memberi -o, hasilnya bernama stdin.pdf, ditulis ke direktori saat ini dengan catatan di error standar.

Skrip sebaiknya mencocokkan alasan, bukan pesan

Kode keluar Arti Contoh
0 Berhasil, atau alat filter bersyarat tanpa kecocokan Penggabungan berhasil; syarat filter-page-count salah
1 Permintaan terkirim tetapi gagal; dalam batch, setidaknya satu berkas gagal Kata sandi salah, bukan PDF, batas waktu habis, tidak ada yang dikembalikan
2 Kesalahan pemakaian, tidak ada yang diunggah Nama alat salah eja, langkah pipeline yang butuh berkas kedua, tipe hasil yang bertentangan dengan ekstensi berkas keluaran
130 Anda menghentikannya Ctrl-C saat batch

Saat gagal, selain satu baris pesan, error standar membawa tiga baris: reason:, code:, dan hint:. Berkas terenkripsi dengan kata sandi salah menghasilkan ini secara lokal:

pdfx: HTTP 400: The password is incorrect.
reason: wrong_password
code: bad_request
hint: Check the password and try again.

Cara Anda memberikan kata sandi mengubah baris pertama pesan: unlock --password menghasilkan baris di atas. Dengan --input-password pada alat lain, server memperlakukan pembukaan kunci sebagai langkah internal dan baris pertamanya adalah HTTP 400: Pipeline step 0 (security/remove-password) failed: The password is incorrect., sedangkan baris reason: adalah wrong_password pada kedua kasus. Tanpa kata sandi sama sekali pesannya This PDF is password-protected. Enter its password. dan reason adalah password_required. Skrip sebaiknya mencocokkan baris reason:. code lebih kasar, dan nilai yang umum adalah bad_request.

Nama alat yang salah eja keluar dengan 2, dan pesannya menyarankan nama yang mirip:

pdfx: Unknown tool "compres". Did you mean: compress, decompress-pdf? Run `pdfx list` to see all tools.

Tipe hasil yang bertentangan dengan nama berkas juga keluar dengan 2, dan itu terjadi sebelum apa pun ditulis. Menulis ZIP yang dihasilkan Pisahkan PDF ke x.pdf:

pdfx: The result is application/zip but "x.pdf" has a .pdf extension; name it *.zip or write into a directory
code: output_mismatch

Batas waktu habis juga keluar dengan 1, dengan code bernilai timeout. Satuan --timeout adalah milidetik dan nilai bawaannya 300000, yaitu 5 menit, jadi --timeout 60 berarti 60 milidetik, bukan 60 detik.

Saat syaratnya salah, kode keluar tetap 0

Satu kelompok alat menjawab pertanyaan ya atau tidak: apakah jumlah halaman lebih dari N, apakah berkas memuat teks tertentu, apakah berkas lebih besar dari ukuran tertentu. Bila jawabannya ya, mereka mengembalikan berkas input tanpa perubahan; bila tidak, mereka tidak mengembalikan apa pun, dan pdfx mencetak satu baris no match lalu keluar dengan 0. Alat filter ini hanya ada di SDK, baris perintah, dan MCP; situs web tidak punya halaman untuk mereka.

Ini berbeda dari jenis hasil kosong yang lain. Ketika PDF ke CSV tidak menemukan tabel di PDF, server mengembalikan 204 dan pdfx keluar dengan 1 serta melaporkan no_content: alat itu dimaksudkan menghasilkan konten dan tidak menghasilkannya, dan alasannya ada di Ekspor tabel kosong (204): PDF Anda kemungkinan tanpa kolom. Bagi alat filter, "tidak cocok" adalah jawaban yang memang seharusnya diberikan.

Untuk membacanya di skrip, pakai --json. Bila cocok, yang tercetak adalah info berkas yang ditulis; bila tidak cocok, tercetak { "matched": false }:

# Cocok: berkas ditulis, dan infonya dicetak
$ pdfx filter-page-count three.pdf --pageCount 2 --comparator Greater --json -o big/
{ "path": "big/three.pdf", "contentType": "application/pdf", "bytes": 2594 }

# Tidak cocok: tidak ada berkas yang ditulis
$ pdfx filter-page-count three.pdf --pageCount 5 --comparator Greater --json
{ "matched": false }

Untuk hanya menyimpan berkas dengan lebih dari 2 halaman, Anda dapat menulisnya seperti ini. Kami menjalankannya secara lokal pada a.pdf (1 halaman) dan three.pdf (3 halaman), dan hanya yang terakhir yang disimpan:

mkdir -p big
for f in *.pdf; do
  if pdfx filter-page-count "$f" --pageCount 2 --comparator Greater --json -o big/ \
      | jq -e '.matched == false' >/dev/null; then
    echo "$f: dilewati"
  fi
done

jq -e '.matched == false' keluar dengan 0 bila tidak ada kecocokan dan 1 bila ada. Pada kecocokan, berkas sudah ditulis ke big/ oleh pdfx; if hanya menentukan apakah "dilewati" dicetak, bukan apakah berkas ditulis.

Dengan satu input saja, --json tidak punya array files

Dengan beberapa input, output standar di bawah --json adalah laporan lengkap. input adalah jalur absolut. processed menghitung berkas yang permintaannya berhasil, termasuk yang tanpa kecocokan. unmatched adalah jumlah dari berkas itu yang tidak cocok, dan entri mereka berbentuk { "ok": true, "matched": false } tanpa path. Bila setiap berkas dalam batch tidak cocok, kode keluar tetap 0. Bila Anda memberikan --idempotency-key ke batch, kunci yang dikirim untuk tiap berkas adalah <key>:<index>; mekanismenya ada di Idempotency-Key: percobaan ulang yang aman untuk pekerjaan PDF.

{
  "processed": 2,
  "unmatched": 0,
  "failed": 1,
  "files": [
    { "input": "/work/a.pdf", "ok": true, "path": "out/a.pdf", "contentType": "application/pdf", "bytes": 1040 },
    { "input": "/work/broken.pdf", "ok": false, "error": "HTTP 400: The file is not a valid PDF or it is damaged.", "reason": "invalid_pdf" },
    { "input": "/work/b.pdf", "ok": true, "path": "out/b.pdf", "contentType": "application/pdf", "bytes": 1027 }
  ]
}

Dengan satu input, jalur berkas tunggal yang dipakai: --json mencetak { "path": ..., "contentType": ..., "bytes": ... } dan tidak ada array files. Saat gagal, output standar kosong dan semuanya ada di error standar. Bila Anda mengembangkan berkas dengan glob, skrip harus menangani kedua format, entah satu berkas yang cocok atau beberapa.

Kumpulkan aturan di atas dalam satu langkah CI

Skrip ini hanya mengompres dan tidak memakai alat filter. Kegagalan kompresi keluar dengan 1, dan langkahnya ikut gagal. Alat filter tanpa kecocokan keluar dengan 0, sehingga CI tidak gagal hanya karena tidak ada kecocokan; apakah ketiadaan kecocokan dianggap masalah, Anda yang memutuskan dengan membaca --json, seperti di bagian filter di atas.

Jika ada berkas yang ditolak, langkah ini gagal dan mencantumkan nama berkas beserta alasannya di log. Logikanya sama seperti sebelumnya: baca kode keluar lebih dulu, cetak error standar saat gagal, lalu pakai jq untuk mengambil reason dari laporan batch. Tanpa argumen direktori, skrip langsung keluar, agar "$1"/*.pdf tidak pernah terurai menjadi /*.pdf.

#!/usr/bin/env bash
# Pemakaian: ./ci-step.sh docs
docs="${1:?usage: ./ci-step.sh <direktori>}"
mkdir -p out
pdfx compress "$docs"/*.pdf -o out/ --json > report.json 2> errors.log
status=$?
if [ "$status" -ne 0 ]; then
  cat errors.log >&2
  jq -r '.files[]? | select(.ok | not) | "\(.input | split("/") | last)\t\(.reason)"' report.json >&2
fi
exit "$status"

Kami menjalankannya secara lokal dengan empat jenis input:

Berkas di direktori Kode keluar Log
Dua PDF yang baik 0 tidak ada
Dua PDF yang baik ditambah satu yang rusak 1 pdfx: broken.pdf: HTTP 400: ..., lalu satu baris broken.pdf invalid_pdf
Satu PDF yang baik 0 tidak ada; report.json berformat berkas tunggal
Satu PDF yang rusak 1 reason: invalid_pdf, code: invalid_document dan satu baris hint; report.json kosong

Tanda tanya di akhir .files[]? pada jq mencegah laporan berkas tunggal (yang tidak punya files) memunculkan galat. Satu berkas rusak tidak punya laporan batch dan alasannya hanya muncul di errors.log, jadi simpan kedua keluaran itu.

Tiga hal lagi yang perlu diperiksa sebelum Anda memasang ini di CI. pdfx membutuhkan jaringan: berkas diunggah ke PDFX_API_BASE, yang bawaannya https://pdf123.xyz. Untuk dokumen yang harus tetap berada di jaringan Anda, jalankan layanan sendiri dan arahkan variabel ini ke sana; lihat Apa yang benar-benar Anda dapatkan dari self-hosting (dan biayanya). Bila Anda membutuhkan identitas, taruh kunci di PDFX_API_KEY dan bukan di argumen baris perintah, tempat ia akan tertinggal di daftar proses dan log. Versi yang saat ini terbit adalah 0.1.0; di CI pakai npx @pdf123/[email protected] ... untuk mengunci versinya, agar format output dan kode keluar tidak berubah mengikuti rilis baru dan peningkatan versi menjadi perubahan yang Anda lakukan dengan sengaja.

Halaman paket di npm adalah @pdf123/cli.

Open tool
Process in the browser β€” no watermark, files removed after the job.
Open tool