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,' &gt; /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,' &gt; /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 &lt;(pdftotext /path/to/pdf-file-1 -) &lt;(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 命令)

如何获得一个bash子进程的命令行上的进程id

在 Linux 命令行上以编程方式删除所有蓝牙设备

用awk如何读取shell命令行上的参数(参数可以是带空格的)

如何在 linux 命令行上找到可能位于任何位置的文件/目录? [关闭]