\href{myfile.pdf#page.42}{link text}
我知道我们可以在 Linux 中使用命令行导出指定的 PDF 目标(外部链接的超级目标,就像我们可以在 LaTeX 中引用它们一样) pdfinfo -dests
。
但是,我们如何使用命令行工具在从某处收到的现成 PDF 文件中添加/创建这样的命名目标链接呢?
答案1
根据 @meuh 的提示,指向 Adobe 的 PDFpdfmark\hypertarget{}
功能,我发现从文件导入(可能是手工制作的)pdfmarks(用于使用命名目的地之类的东西,就像它们将由 LaTeX 等创建的那样)的工作可以通过 Ghostscript 完成,例如:
gs -q -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -dPDFDontUseFontObjectNum -dPrinted=false -sOutputFile=FILE_NEW.pdf FILE_ORIGINAL.PDF PDFMARKS_TO_BE_ADDED_TO.ps
...程序的手册页建议extractpdfmark
(包含在许多 Linux 发行版中,源代码位于https://github.com/trueroad/extractpdfmark),它的作用是将一个 PDF 文件的所有 pdfmarks(导航链接、命名目的地等)显示/导出为 postscript PS 文件,然后可以通过上述ghostscript
命令行将其重新导入到其他文件中 – 例如使用原始文件包含目的地的情况,然后在进程之间的某些过程中丢失,并且必须重新导入(就像在我的完整用例中一样,我没有详细描述,因为该部分在这里似乎不相关)。
导入之后,就可以(再次)从 LaTeX 成功链接到该文件的特定 PDF 页面。
以下代码片段可能会简化所描述用例的过程:
#!/bin/bash
# copy pdfmarks from a SOURCE_FILE .pdf to the existing TARGET_FILE .pdf
SOURCE_FILE=$1
TARGET_FILE=$2
PDFMARKS=$(mktemp)
TMPFILE=$(mktemp)
extractpdfmark "${SOURCE_FILE}" > "${PDFMARKS}"
cp "${TARGET_FILE}" ${TMPFILE}
# combine exported PDFMARKS with the content of the TARGET_FILE into the TMPFILE copy of the target file
gs -q -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -dPDFDontUseFontObjectNum -dPrinted=false \
-sOutputFile=${TMPFILE} "${TARGET_FILE}" "${PDFMARKS}"
cp ${TMPFILE} "${TARGET_FILE}"
(只是添加这个,因为在我的经验的许多转换过程中出现了不需要的副作用:此外,通过 Xournal 或 Okular 完成的注释之类的事情在添加 pdfmarks 后仍然像以前一样,但书签/目录似乎没有被接管,也许为此使用pdftk
的功能。)dump_data
另请注意:要为 PDF 生成一些简单的目标,只需创建一个文件,例如pdfmarks.ps
:
% manually crafted
[ /PageMode /UseOutlines /DOCVIEW pdfmark
然后运行命令行片段:
for i in $(seq 1 999); do
echo "[ /Dest (page.$i) /Page $i /View [/Fit] /DEST pdfmark" >> pdfmarks.ps
done
生成超级目标作为 999 个页面的指定目的地,您可以将其与上面的 Ghostscript 命令一起使用,将其添加到另一个 PDF。 (请注意,对于 PS,一行中的第一个方括号在末尾不闭合。)
答案2
这也许不是最好的方法,但您可以使用 LaTeX 本身来做到这一点,使用pdfpages
和hyperref
包的组合。
假设您有一个名为 inputfile.pdf 的 PDF。您可以通过像这样创建一个包装器来添加一些命名目的地,并使用\includepdf
包含picturecommand=
命令的选项\hypertarget
。
\documentclass{article}
\usepackage{pdfpages,hyperref}
\pagestyle{empty}
\begin{document}
% put two named destinations on page 1
\includepdf[pages=1,
picturecommand={
\put(100,100){\hypertarget{mydestination2}{}}
\put(200,250){\hypertarget{anotherdestination3}{}}
}
]{inputfile}
% put a named destination on page 2
\includepdf[pages=2,
picturecommand={
\put(200,100){\hypertarget{yetanother}{}}
}
]{inputfile}
% put rest of pages as is with only page number targets
\includepdf[pages=3-]{inputfile}
\end{document}
这些\put(x,y)
命令会将目标放置在页面上相对于左下角的特定位置。这些与您使用时看到的数字相同或至少非常接近pdfinfo -dests
。
表单的目标page.###
将自动插入,因此您可以“免费”获得这些目标。
如果您想从命令行执行此操作而不创建中间 LaTeX 文件,则该pdfjam
实用程序基本上只是带有pdfpages
包的 LaTeX 的包装器。所以你可以使用这样的东西:
pdfjam --preamble '\usepackage{hyperref}' --picturecommand'*' '{\put(300,300){\hypertarget{destname}{}}}' inputfile.pdf --outfile outputfile.pdf
将指定的目标位置放置在 300x300 的首页中inputfile.pdf
。请参阅 参考资料 来了解pdfjam --help
有关执行更高级操作的更多信息。
这些方法的真正缺点是它们不保留任何可能已经存在的目的地。然而,我认为这对于还没有这些 PDF 的 PDF 很有用,您也许可以使用pdfinfo -dests
和 此方法的组合来编写重新插入旧 PDF 的脚本。