Skip to content

Commit ffc4222

Browse files
Merge PDFs: add CLI for merging/inserting PDFs with validation; preserve original helpers
1 parent c7cb790 commit ffc4222

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

Merge PDFs/merge.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
from PyPDF2 import PdfFileMerger
2+
import argparse
3+
import sys
4+
5+
try:
6+
from PyPDF2 import PdfMerger # new name
7+
except ImportError:
8+
from PyPDF2 import PdfFileMerger as PdfMerger # fallback for older versions
29

310

411
def by_appending():
@@ -8,14 +15,89 @@ def by_appending():
815
merger.append("testPDF12.pdf")
916

1017
merger.write("mergedPDF.pdf")
18+
f1.close
1119

1220
def by_inserting():
1321
merger = PdfFileMerger()
1422
merger.append("testPDF1.pdf")
1523
merger.merge(0, "testPDF2.pdf")
1624
merger.write("mergedPDF.pdf")
1725

26+
def merge_pdfs(pdfs: list[Path], output: Path) -> None:
27+
"""Append all given PDFs in order and write to output."""
28+
merger = PdfMerger()
29+
files = []
30+
try:
31+
for pdf in pdfs:
32+
fh = pdf.open("rb")
33+
files.append(fh)
34+
merger.append(fh)
35+
merger.write(str(output))
36+
print(f"[ok] Merged {len(pdfs)} PDFs into {output}")
37+
finally:
38+
for fh in files:
39+
fh.close()
40+
41+
42+
def insert_pdf(pdfs: list[Path], insert: Path, index: int, output: Path) -> None:
43+
"""Append PDFs and insert another at given index."""
44+
merger = PdfMerger()
45+
files = []
46+
try:
47+
for pdf in pdfs:
48+
fh = pdf.open("rb")
49+
files.append(fh)
50+
merger.append(fh)
51+
52+
with insert.open("rb") as ins_fh:
53+
merger.merge(index, ins_fh)
54+
55+
merger.write(str(output))
56+
print(f"[ok] Inserted {insert} at index {index} -> {output}")
57+
finally:
58+
for fh in files:
59+
fh.close()
60+
61+
62+
def parse_args(argv):
63+
parser = argparse.ArgumentParser(description="Merge multiple PDFs")
64+
parser.add_argument("pdfs", nargs="+", help="Input PDF files")
65+
parser.add_argument("-o", "--output", default="mergedPDF.pdf", help="Output file name")
66+
parser.add_argument("--insert", help="Optional PDF to insert")
67+
parser.add_argument("--at", type=int, default=0, help="Index to insert at (default=0)")
68+
return parser.parse_args(argv)
69+
70+
71+
def validate(paths: list[str]) -> list[Path]:
72+
pdfs = []
73+
for p in paths:
74+
path = Path(p)
75+
if not path.exists():
76+
sys.exit(f"[error] File not found: {path}")
77+
if path.suffix.lower() != ".pdf":
78+
sys.exit(f"[error] Not a PDF: {path}")
79+
pdfs.append(path)
80+
return pdfs
81+
82+
83+
def main(argv=None):
84+
args = parse_args(argv or sys.argv[1:])
85+
pdfs = validate(args.pdfs)
86+
out = Path(args.output)
87+
88+
if args.insert:
89+
insert = validate([args.insert])[0]
90+
insert_pdf(pdfs, insert, args.at, out)
91+
else:
92+
if len(pdfs) < 2:
93+
sys.exit("[error] Need at least 2 PDFs to merge")
94+
merge_pdfs(pdfs, out)
95+
96+
1897

1998
if __name__ == "__main__":
99+
20100
by_appending()
21101
by_inserting()
102+
103+
main()

0 commit comments

Comments
 (0)