1
1
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
2
9
3
10
4
11
def by_appending ():
@@ -8,14 +15,89 @@ def by_appending():
8
15
merger .append ("testPDF12.pdf" )
9
16
10
17
merger .write ("mergedPDF.pdf" )
18
+ f1 .close
11
19
12
20
def by_inserting ():
13
21
merger = PdfFileMerger ()
14
22
merger .append ("testPDF1.pdf" )
15
23
merger .merge (0 , "testPDF2.pdf" )
16
24
merger .write ("mergedPDF.pdf" )
17
25
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
+
18
97
19
98
if __name__ == "__main__" :
99
+
20
100
by_appending ()
21
101
by_inserting ()
102
+
103
+ main ()
0 commit comments