如果我考虑一个简单的 LaTeX 文档,例如:
\documentclass[11pt]{article}
\begin{document}
Hello, World!
\end{document}
如果我多次排版我每次都会得到不同的校验和
$ pdflatex test
This is pdfTeX, Version 3.1415926-1.40.10 (TeX Live 2009)
restricted \write18 enabled.
entering extended mode
...
Output written on test.pdf (1 page, 12592 bytes).
Transcript written on test.log.
$ cksum test.pdf
2770399004 12592 test.pdf
$ pdflatex test
This is pdfTeX, Version 3.1415926-1.40.10 (TeX Live 2009)
restricted \write18 enabled.
entering extended mode
...
Output written on test.pdf (1 page, 12592 bytes).
Transcript written on test.log.
$ cksum test.pdf
1225641903 12592 test.pdf
校验和不同是由于 PDF 文件中三行发生变化:
/CreationDate (D:20101115092454-05'00')
/ModDate (D:20101115092454-05'00')
...
/ID [<E52BBC1CEFDC95455342C233D35D790A> <E52BBC1CEFDC95455342C233D35D790A>] >>
更复杂的 LaTeX 输入也会出现这种情况。有没有办法排版 LaTeX 文件以避免此问题,以便如果排版多次,PDF 文件的校验和保持不变?
答案1
我认为值得在这里重复一下答案。(因为这是来自超级用户,我不应该为此获得任何声誉......所以我将其标记为 CW):
您可以使用 pdftex 的宏来更改 pdf 的信息字典的内容
\pdfinfo
:\def\fixedpdfdate{D:20100413000000+00’00’} \pdfinfo{ /CreationDate (\fixedpdfdate) /ModDate (\fixedpdfdate) }
把这个放在文档的开头:字典可能会被分成几块写出来,有一定的风险。
答案2
SOURCE_DATE_EPOCH
总结
创建一个名为 Makefile 的文件并包含这些内容,然后输入make
。
all: test.pdf
%.pdf: %.tex
SOURCE_DATE_EPOCH=`(git log -1 --format=%at $< 2>/dev/null; \
date +%s -r $<) | head -1` \
pdflatex $<
您无需理解这一点即可使用它。
好奇者的解释
虽然接受的答案很好,但还有另一种解决方案,它不需要修改 .tex 文件,可与任何现代 TeX 引擎(pdfTeX、LuaTeX、XeTeX)配合使用,并且可以在 .tex 文件更改时更新。核心思想是设置环境变量SOURCE_DATE_EPOCH,用于的变量可重复的构建。
固定日期示例
首先,这里有一个类似于已接受答案的示例,它对特定日期进行硬编码,格式为自时代(啦 date +%s
)。
$ export SOURCE_DATE_EPOCH=1694000000
$ pdflatex test.tex && md5sum test.pdf
badef9728436749defaec3982f86e4e0 test.pdf
$ pdflatex test.tex && md5sum test.pdf
badef9728436749defaec3982f86e4e0 test.pdf
$ pdfinfo test.pdf | grep Mod
ModDate: Wed Sep 6 11:33:20 2023 UTC
这可行,但请继续阅读以找到更好的方法。
使用 latex 文件的修改时间
根据您是否将 latex 文件存储在 git 存储库中,您可以使用以下方法之一来检索修改时间:
- 使用 git:
git log -1 --format=%at test.tex
- 没有 git:
date +%s -r test.tex
例如,
SOURCE_DATE_EPOCH=`git log -1 --format=%at test.tex` pdflatex test.tex
综合起来
上述命令可以包装在 shell 脚本中或Makefile。下面是后者的一个例子,它使用 git(如果可用)并回退到文件修改时间戳:
all: test.pdf
# Pattern rule for building a pdf from any latex source file.
# Note: $< represents the .tex filename.
%.pdf: %.tex FORCE
SOURCE_DATE_EPOCH=`(git log -1 --format=%at $< 2>/dev/null; \
date +%s -r $<) | head -1` \
pdflatex $<
FORCE:
要使用它,只需键入make
create test.pdf。或者,由于它使用模式规则,您可以键入make foo.pdf
,它会查找名为 foo.tex 的文件。
注意:FORCE
目标是可选的。它允许您make
根据需要重复运行以重新运行 pdflatex,以进行交叉引用和参考书目。