Linux命令行上的PDF比较
Posted
技术标签:
【中文标题】Linux命令行上的PDF比较【英文标题】:PDF compare on linux command line 【发布时间】:2011-09-22 02:05:09 【问题描述】:我正在寻找一个 Linux 命令行工具来比较两个 PDF 文件并将差异保存到 PDF 输出文件。该工具应该在批处理中创建 diff-pdf。 PDF 文件是施工图,所以纯文本比较不起作用。
类似:
<tool> file1.pdf file2.pdf -o diff-out.pdf
我发现的大多数工具都可以将 PDF 转换为图像并进行比较,但只能使用 GUI。
也欢迎任何其他解决方案。
【问题讨论】:
这不是一个编程问题,你需要一个现有的工具来完成一项任务。 两个施工计划之间的“差异”是什么样的?这听起来太内容敏感,无法通过通用比较程序“区分”。 【参考方案1】:我已经编写了自己的脚本,该脚本的功能与您的要求相似。该脚本使用 4 个工具来实现其目标:
-
ImageMagick 的
compare
命令
pdftk
实用程序(如果您有多页 PDF)
Ghostscript(可选)
md5sum
(可选)
将它移植到 DOS/Windows 的 .bat
批处理文件应该很容易。
但首先,请注意:这仅适用于具有相同页面/媒体大小的 PDF。在两个输入 PDF 之间逐个像素地进行比较。生成的文件是显示“差异”的图像,如下所示:
保持不变的每个像素都变成白色。 每个被更改的像素都被涂成红色。该差异图像被保存为新的 PDF,以便在不同的操作系统平台上更好地访问。
例如,当 PDF 处理中的字体替换发挥作用时,我使用它来发现最小的页面显示差异。
您的 PDF 之间可能没有明显的差异,尽管它们的 MD5 哈希值和/或文件大小不同。在这种情况下,“diff”输出 PDF 页面将变为全白。您可以自动发现这种情况,因此您只需通过自动删除全白 PDF 来直观地调查非白色 PDF。
这里是构建块:
pdftk
使用此命令行实用程序将多页 PDF 文件拆分为多个单页 PDF:
pdftk file_1.pdf burst output somewhere/file_1---page_%03d.pdf
pdftk file_2.pdf burst output somewhere/file_2---page_%03d.pdf
如果您只比较单页 PDF,则此构建块是可选的。既然你说的是“建设计划”,那很可能就是这样。
比较
使用 ImageMagick 中的这个命令行实用程序为每个页面创建一个“差异”PDF 页面:
compare \
-verbose \
-debug coder \
-log "%u %m:%l %e" \
somewhere/file_1---page_001.pdf \
somewhere/file_2---page_001.pdf \
-compose src \
somewhereelse/file_1--file_2---diff_page_001.pdf
鬼脚本
由于自动插入元数据(例如当前日期+时间),PDF 输出不适用于基于 MD5hash 的文件比较。
如果您想自动发现差异 PDF 包含纯白页的所有情况,您应该使用 bmp256
输出设备将 PDF 页面转换为无元数据位图格式。你可以这样做:
首先,找出您的 PDF 的页面大小格式是什么。同样,这个小实用程序identify
是任何 ImageMagick 安装的一部分:
identify \
-format "%[fx:(w)]x%[fx:(h)]" \
somewhereelse/file_1--file_2---diff_page_001.pdf
您可以像这样将该值存储在环境变量中:
export my_size=$(identify \
-format "%[fx:(w)]x%[fx:(h)]" \
somewhereelse/file_1--file_2---diff_page_001.pdf)
现在 Ghostscript 开始发挥作用,使用包含上述发现的页面大小的命令行,因为它存储在变量中:
gs \
-o somewhereelse/file_1--file_2---diff_page_001.ppm \
-sDEVICE=ppmraw \
-r72 \
-g$my_size \
somewhereelse/file_1--file_2---diff_page_001.pdf
这为您提供了一个分辨率为 72 dpi 的 PPM(便携式 PixMap),来自原始 PDF 页面。 72 dpi 通常足以满足我们的需求...接下来,创建一个具有相同页面大小的纯白色 PPM 页面:
gs \
-o somewhereelse/file_1--file_2---whitepage_001.ppm \
-sDEVICE=ppmraw \
-r72 \
-g$my_size \
-c "showpage"
-c "showpage"
部分是一个 PostScript 命令,它告诉 Ghostscript 只发出一个空页面。
MD5 和
使用 MD5 哈希自动比较原始 PPM 和白页 PPM。如果它们相同,您可以假设 PDF 之间没有差异,因此重命名或删除 diff-PDF:
MD5_1=$(md5sum somewhereelse/file_1--file_2---diff_page_001.ppm | awk 'print $1')
MD5_2=$(md5sum somewhereelse/file_1--file_2---whitepage_001.ppm | awk 'print $1')
if [ "x$MD5_1" == "x$MD5_2" ]; then
mv \
somewhereelse/file_1--file_2---diff_page_001.pdf \
somewhereelse/file_1--file_2---NODIFFERENCE_page_001.pdf # rename all-white PDF
rm \
somewhereelse/file_1--file_2---*_page_001.ppm # delete both PPMs
fi
这使您不必目视检查没有任何差异的“差异 PDF”。
【讨论】:
非常酷,谢谢。实际上我还没有找到任何直接进行pdf-compare的工具。他们都使用pdf来图像导出和比较图像文件。我会试试这个。 好主意!这里有更多。要验证您的文件(或其中的一页)是否为纯白色,您可以使用直方图:convert file.pdf -format %c histogram:info: | grep -Ev '^$|255,255,255,' > /dev/null
将返回您0
如果页面上没有白色的东西。您还可以通过使用 subsctripion:compare file1.pdf[42] file2.pdf[42] -compose src output.png
直接将 compare
用于 PDF 页面。 A now all together: compare "$src[$i]" "$dst[$i]" -compose src -format %c histogram:info: | grep -Ev '^$|255,255,255,' > /dev/null
如果页面 #i 在这些 PDF 中不同,您将获得成功。
谢谢,我刚遇到这个,你帮了我很多。
@Yorik.sar 使用 grep 的好主意,但是当我运行它时,转换输出 484704: (65535,65535,65535,65535) #FFFFFFFFFFFF white
,所以它没有您正在寻找的 255,255,255
。最好只搜索white
your own script
是否可以在某处下载?例如,作为一个要点?)【参考方案2】:
这里有一个技巧。
pdftotext file1.pdf
pdftotext file2.pdf
diff file1.txt file2.txt
【讨论】:
谢谢,但 pdf 文件是施工图,所以没有文字。 以下命令与答案中列出的命令相同,但在一行中:vimdiff <(pdftotext /path/to/pdf-file-1 -) <(pdftotext /path/to/pdf-file-2 -)
【参考方案3】:
用(全能的)imagemagick 和 pdftk 分两行完成:
compare -verbose -debug coder $PDF_1 $PDF_2 -compose src $OUT_FILE.tmp
pdftk $OUT_FILE.tmp background $PDF_1 output $OUT_FILE
选项 -verbose 和 -debug 是可选的。
compare 会创建一个 PDF,其中 diff 为红色像素。 pdftk 将 diff-pdf 与背景 PDF_1 合并【讨论】:
好...您从我的答案中提取了核心命令行并剥离了其余部分。也许您不需要比较我的方法涵盖的多页 PDF 和一些额外的极端情况......以上是关于Linux命令行上的PDF比较的主要内容,如果未能解决你的问题,请参考以下文章
在 Linux 命令行上检查 postgresql jdbc 驱动程序版本的命令是啥?
在 windows 的命令行上创建一个空文件(如 linux touch 命令)