emacs-合并dired中pdf文件
windows 上有一个开源软件 pdfpatcher ,有很方便的拆分、合并 pdf 功能。正巧, emacs 上也有一个类似的 package pdftk-dired,可以通过开源的 pdftk 简单操作 pdf 文件。
不过在 emacs 中,用命令行搞拆分之类复杂功能有点折磨自己了,所以我把其中的合并文件功能提取了出来,利用ai优化了下逻辑,单独使用:
(defun pdftk-merge (filenames output-file)
"Merge PDF files listed in FILENAMES and save them to OUTPUT-FILE.
FILENAMES is a list of filenames to be merged, while OUTPUT-FILE
is the path where the new PDF should be saved.
This function requires 'pdftk' command-line tool to be installed
and available in the system's PATH.
Example: (pdftk-merge
'(\"/path/to/input_1.pdf\" \"/path/to/input_2.pdf\")
\"/path/to/output.pdf\")"
;; 1. 检查是否安装了 pdftk
(unless (executable-find "pdftk")
(error "Command 'pdftk' not found. Please install it first"))
;; 2. 将所有文件路径转换为绝对路径,避免因为 default-directory 改变导致找不到文件
(let* ((abs-filenames (mapcar #'expand-file-name filenames))
(abs-output (expand-file-name output-file))
;; 3. 构建参数列表 (不需要手动处理引号了)
(args (append abs-filenames (list "cat" "output" abs-output)))
;; 4. 使用 call-process 直接调用程序,规避 shell 注入和转义问题
(exit-code (apply #'call-process "pdftk" nil nil nil args)))
;; 5. 检查退出状态码
(if (zerop exit-code)
(message "Successfully merged PDFs into %s" output-file)
(error "pdftk failed to merge files (exit code %d)" exit-code))
abs-output))
(defun my/dired-merge-pdfs ()
"Merge selected PDF files in Dired.
Note: Files are merged in the order they appear in the Dired buffer.
This function prompts the user for an output file name and then
merges the marked PDF files into this new file."
(interactive)
;; 1. 确保在 Dired 模式下运行
(unless (derived-mode-p 'dired-mode)
(error "This command must be run in a Dired buffer"))
(let* ((all-marked (dired-get-marked-files))
;; 2. 过滤掉非 PDF 文件和目录,确保安全
(pdf-files (seq-filter (lambda (f)
(and (not (file-directory-p f))
(string-match-p "\\.[pP][dD][fF]\\'" f)))
all-marked)))
;; 3. 检查是否有足够的文件进行合并
(when (< (length pdf-files) 2)
(error "Please mark at least 2 PDF files to merge"))
(let* ((default-output-file "merged.pdf")
;; 4. 优化交互提示,使用当前目录作为默认路径
(output-file (read-file-name "Output file: "
default-directory
default-output-file
nil
default-output-file)))
;; 5. 执行合并
(pdftk-merge pdf-files output-file)
;; 6. 刷新 Dired buffer,让新生成的文件显示出来
(revert-buffer))))
(use-package dired
;; 内置包
:ensure nil
:config
(defun my/dired-narrow ()
(interactive)
(call-interactively #'dired-mark-files-regexp)
(command-execute "tk"))
:bind
(:map dired-mode-map
("M-m" . my/dired-merge-pdfs)
("/" . my/dired-narrow)))
原版可以通过按键的顺序自定义合并顺序,而这一修改版的特点是文件合并顺序以 dired 中的显示排序为准。优点则是不需要占用其他按键或者自定义按键以执行标记功能,只需要按 m mark 之后按下 M-m 执行 my/dired-merge-pdfs 就可以合并了。