-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpdfmerger.py
More file actions
77 lines (61 loc) · 2.27 KB
/
Copy pathpdfmerger.py
File metadata and controls
77 lines (61 loc) · 2.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
"""Merge PDF files from a directory into ``merged.pdf``.
Usage: python3.14 pdfmerger.py DIRECTORY [--sort-type date|prefix] [--no-bookmark]
Requires the ``pypdf`` package.
"""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
from pypdf import PdfWriter
def prefix_key(path: Path) -> tuple[float, str]:
prefix = path.name.split("_", 1)[0]
return (float(prefix) if prefix.isdigit() else float("inf"), path.name.casefold())
def date_key(path: Path) -> float:
return path.stat().st_mtime
def name_key(path: Path) -> str:
return path.name.casefold()
def merge_pdfs(
directory: Path,
*,
sort_type: str | None = None,
bookmarks: bool = True,
output: Path = Path("merged.pdf"),
) -> int:
"""Merge PDFs and return the number of input files."""
files = [path for path in directory.iterdir() if path.is_file() and path.suffix.lower() == ".pdf"]
if sort_type == "date":
files.sort(key=date_key)
elif sort_type == "prefix":
files.sort(key=prefix_key)
else:
files.sort(key=name_key)
if not files:
raise ValueError("no PDF files found")
writer = PdfWriter()
try:
for path in files:
bookmark = path.stem if bookmarks else None
print(f"Merging: {path.name}")
writer.append(path, outline_item=bookmark)
with output.open("wb") as handle:
writer.write(handle)
finally:
writer.close()
return len(files)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Merge PDF files from a directory.")
parser.add_argument("path", type=Path, help="directory containing PDF files")
parser.add_argument("--sort-type", choices=("date", "prefix"))
parser.add_argument("--no-bookmark", action="store_true")
args = parser.parse_args(argv)
if not args.path.is_dir():
parser.error(f"directory not found: {args.path}")
try:
count = merge_pdfs(args.path, sort_type=args.sort_type, bookmarks=not args.no_bookmark)
except (OSError, ValueError) as exc:
print(f"Error: {exc}", file=sys.stderr)
return 1
print(f"Done. Merged {count} files into merged.pdf")
return 0
if __name__ == "__main__":
raise SystemExit(main())