PDF如何批量列出PDF有注释?qpdf吗?pdfinfo吗?



当我打印一个我用Okular注释的pdf时,打印没有注释,尽管它确实显示在屏幕上,但我很惊讶。我必须先把加了注释的文件存为打印后的pdf文件,然后再打印。

问题:如何列出至少一个页面上至少有一个注释的所有pdf ?

显然,当有注释

时,pdfinfo返回Acroform
            find -type f -iname "*.pdf" -exec pdfinfo {} ;

但不显示文件名。

我不熟悉qpdf,但它似乎没有提供这个信息

感谢

使用pdfinfo from poppler-utils,你可以说,

find . -type f -iname '*.pdf' | while read -r pn
do  pdfinfo "$pn" |
    grep -q '^Form: *AcroForm' && printf '%sn' "$pn"
done

列出pdfinfo报告的PDF文件的名称:

Form:           AcroForm

然而,在我的测试中,它遗漏了几个带有文本注释的pdf并列出了几个没有的,所以我不会为了这份工作而使用它。下面是2个alternatives: qpdf支持所有注释子类型,python3-poppler-qt5只是一个子集,但可以快得多。

(对于非posix shell,请使用本文中的命令)

编辑: find构造被编辑以避免不安全和依赖gnu的{} s。


qpdf版本从8.3.0开始支持json表示非内容PDF数据,如果您的系统使用jqJSON处理器,您可以列出唯一的PDF注释类型选项卡分隔的值(在本例中丢弃输出并使用只有退出代码):

find . -type f -iname '*.pdf' | while read -r pn
do  qpdf --json --no-warn -- "$pn" |
    jq -e -r --arg typls '*' -f annots.jq > /dev/null && 
    printf '%sn' "$pn"
done

,

  • --arg typls '*'指定所需的注释子类型,例如*用于所有选项(默认),或用于
  • 选项的Text,FreeText,Link
  • -e设置退出码4,如果没有输出(没有发现注释)
  • -r生成原始(非json)输出
  • jq脚本文件annots.jq包含以下内容
#! /usr/bin/env jq-1.6
def annots:
    ( if ($typls | length) > 0 and $typls != "*"
      then $typls
      else
        # annotation types, per Adobe`s PDF Reference 1.7 (table 8.20)
        "Text,Link,FreeText,Line,Square,Circle,Polygon"
        + ",PolyLine,Highlight,Underline,Squiggly,StrikeOut"
        + ",Stamp,Caret,Ink,Popup,FileAttachment,Sound,Movie"
        + ",Widget,Screen,PrinterMark,TrapNet,Watermark,3D"
      end | split(",")
    ) as $whitelist
    | .objects
    | .[]
    | objects
    | select( ."/Type" == "/Annot" )
    | select( ."/Subtype" | .[1:] | IN($whitelist[]) )
    | ."/Subtype" | .[1:]
    ;
[ annots ] | unique as $out
| if ($out | length) > 0 then ($out | @tsv) else empty end

对于许多用途,使用python-3是诱人的。xpython3-poppler-qt5要一次性处理整个文件列表,

find . -type f -iname '*.pdf' -exec python3 path/to/script -t 1,7 {} '+'

,其中-t选项列出了所需的注释子类型波普尔文档;1为AText, 7为ALink。没有-t的所有已知亚型选择Poppler(0到14),即不是所有现有的子类型支持。

#! /usr/bin/env python3.8
import popplerqt5
def gotAnnot(pdfPathname, subtypls):
    pdoc = popplerqt5.Poppler.Document.load(pdfPathname)
    for pgindex in range(pdoc.numPages()):
        annls = pdoc.page(pgindex).annotations()
        if annls is not None and len(annls) > 0:
            for a in annls:
                if a.subType() in subtypls:
                    return True
    return False
if __name__ == "__main__":
    import sys, getopt
    typls = range(14+1)         ## default: all subtypes
    opts, args = getopt.getopt(sys.argv[1:], "t:")
    for o, a in opts:
        if o == "-t" and a != "*":
            typls = [int(c) for c in a.split(",")]
    for pathnm in args:
        if gotAnnot(pathnm, typls):
            print(pathnm)

最新更新