(La)TeX 可以比较两个外部文件的时间戳吗?

(La)TeX 可以比较两个外部文件的时间戳吗?

设想

我有一堆独立的 PSTricks 文件。每个文件都可以通过编译latex-dvips-ps2pdf-pdfcrop-pdftops来生成 PDF 图像。我制作了一个批处理文件来执行此操作latex-dvips-ps2pdf-pdfcrop-pdftops

在我的主要输入文件中,我将遍历 PSTricks 文件。每次迭代时,我都会检查相应的 PDF 是否存在。如果相应的 PDF 已经存在,我会检查其时间戳是否比其.tex文件的时间戳更新。否则,我将调用\immediate\write18 mybatch.bat filename.tex以生成或重新生成相应的 PDF 文件。

问题

(La)TeX 可以比较两个外部文件的时间戳吗?最好能提供上述场景的完整工作源代码。:-)

注意:实际上我可以编写一个外部脚本来遍历 PSTricks 文件,并且只在主输入文件中调用一次该脚本。但我对创建混合解决方案感兴趣。

答案1

filemod专门为这个任务编写了一个包,我也需要在即将发布的版本中使用standalone。它需要 pdf(La)TeX 或 Lua(La)TeX,但不适用于 Xe(La)TeX。

基本用法:

\Filemodcmp{<file 1>}{<file 2>}{<1 is newer>}{<2 is newer>}

还有一个完全可扩展的版本,称为\filemodcmp和宏,用于从给定的列表中查找最新或最旧的文件。

答案2

\def\comparetimestamp#1#2{%
  \ifnum\pdfstrcmp{\pdffilemoddate{#1}}{\pdffilemoddate{#2}}<0
    \message{#1 is older than #2}%
  \fi}

将行更改\message为您需要的内容。不适用于 XeLaTeX,仅适用于 (pdf)latex。如果在运行期间时区发生变化(例如,在切换到或从 DST 切换时),则可能会出现问题,但这应该不是问题。

答案3

你可以使用 luatex。ConTeXt 包装器mtxrun提供了一种基于时间戳的实现

mtxrun --iftouched=file.tex,file.pdf --direct pdflatex file 

以及一个基于 md5 sum 的

mtxrun --ifchanged=file.tex --direct pdflatex file

它创建一个 md5 值,file.tex并且只有当 md5 值发生变化时才运行该命令。请参阅 的源代码mtxrun.lua以了解实现。相关函数如下:

function file.needs_updating(oldname,newname,threshold) -- size modification access change
    local oldtime = lfs.attributes(oldname, modification)
    local newtime = lfs.attributes(newname, modification)
    if newtime >= oldtime then
        return false
    elseif oldtime - newtime < (threshold or 1) then
        return false
    else
        return true
    end
end

function file.checksum(name)
    if md5 then
        local data = io.loaddata(name)
        if data then
            return md5.HEX(data)
        end
    end
    return nil
end

function file.loadchecksum(name)
    if md5 then
        local data = io.loaddata(name .. ".md5")
        return data and (gsub(data,"%s",""))
    end
    return nil
end

其余的只是将它们包装在用户宏周围的问题。

答案4

这个答案与 TeX 无关,但我想指出的是,使用正确的工具可以大大简化解决方案。在这种情况下,你应该使用make。此工具有一个很好的手册这里

下面是一个非常简单的 Makefile(它应该进一步扩展以适应良好的实践):

TARGETS = <要构建的目标列表>(GNU Make 的通配符和 patsubst 可能会有帮助)

.PHONY:全部干净

全部:$(TARGETS)

%.pdf: %.tex
    <在此处调用批处理文件或直接集成命令,$<代表源名称>

干净的:
    $(RM) $(目标)

现在只需make随时输入即可确保目标是最新的。

相关内容