当我打印一个我用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 '*'
指定所需的注释子类型,例如*
用于所有选项(默认),或用于 选项的 -
-e
设置退出码4,如果没有输出(没有发现注释) -
-r
生成原始(非json)输出 -
jq
脚本文件annots.jq
包含以下内容
Text,FreeText,Link
#! /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)