如何防止 graphicx 搜索 TEXINPUTS

如何防止 graphicx 搜索 TEXINPUTS

对于包含大量插图的大型文档,我通常的做法是将图形文件组织到一个或多个子目录中,然后将这些子目录添加到图形路径中,以便\includegraphics可以找到插图:

\documentclass{article}
\usepackage{graphicx}
\graphicspath{{images/}}
\begin{document}
\includegraphics[width=\linewidth]{cc-by-sa}
\end{document}

这种方法的问题在于,如果我的 TeX 安装恰好包含一个名为的文件cc-by-sa.png(巧合的是,TeX Live 2015 也包含这个文件),那么\includegraphics就会使用该图形而不是我的图形。在这种情况下,./images/cc-by-sa.pdf我的文档包含的不是,而是/opt/texlive/2015/texmf-dist/tex/latex/stex/mikoslides/cc-by-sa.png

也许软件包作者有充分的理由来实现这种行为,但我发现这对我的用例来说很不方便。当我为文档中使用的图形文件命名时,我不想手动检查与整个 TeX 安装中的所有图形列表是否冲突(为了安全起见,每次更新 TeX Live 时我都需要这样做,因为软件包作者偶尔会添加图形文件)。

如何才能防止\includegraphics在整个 TeX 安装中查找图形,或者至少首先不查找那里的图形?我希望自己手动指定的图形路径优先。

软件包文档(日期为 2014/04/27)似乎自相矛盾,无法确定这是否可行。第 12 页说\graphicspath“可用于指定搜索图形文件的目录列表”和“此路径的默认设置为\input@path”。对我来说,这意味着存在一个默认值,如果\graphicspath明确设置,它将被覆盖。但是,以下页面建议手动设置\graphicspath只是补充,而不是替代默认值:“请注意,LaTeX 将通过搜索 TEXINPUTS(以及可能使用 指定的其他地方)来找到图形文件\graphicspath”。未指定搜索顺序。

答案1

\includegraphics依赖于\IfFileExists检查文件是否存在并采取行动来确定图片的边界框。

如果\graphicspath已设置,则标准\input@path在本地重置为\Ginput@path(其值来自的参数)\graphicspath

\IfFileExists这里是in的定义latex.ltx(后者,还有一个是在启动时使用的):

\long\def \IfFileExists#1#2#3{%
  \openin\@inputcheck#1 %
  \ifeof\@inputcheck
    \ifx\input@path\@undefined
      \def\reserved@a{#3}%
    \else
      \def\reserved@a{\@iffileonpath{#1}{#2}{#3}}%
    \fi
  \else
    \closein\@inputcheck
    \edef\@filef@und{#1 }%
    \def\reserved@a{#2}%
  \fi
  \reserved@a}

\openin首先使用 TeX 系统设计使用的 来测试文件TEXINPUTS。如果未找到任何内容,\ifeof则为 true 并\input@path用于下一次查找。

因此,\graphicspath始终会查找用 指定的目录系统目录。

唯一的方法(至少是重新定义\IfFileExists)是在调用中指定目录\includegraphics

\includegraphics[width=\linewidth]{./images/cc-by-sa}

\Ginput@path在前面进行查找的(缓慢)实现TEXINPUTS

\documentclass{article}
\usepackage{graphicx}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\slowincludegraphics}{O{}m}
 {
  \psychonaut_ig:nn { #1 } { #2 }
 }

\cs_new_protected:Nn \psychonaut_ig:nn
 {
  \tl_if_in:nnTF { #2 } { / }
   {% an explicit path has been passed
    \includegraphics[#1]{#2}
   }
   {% do the slow processing
    \_psychonaut_ig:nn { #1 } { #2 }
   }
 }
\cs_new_protected:Nn \_psychonaut_ig:nn
 {
  \tl_map_inline:cn { Ginput@path }
   {
    \_psychonaut_file_if_exist:nT { ##1#2 }
     {
      \tl_map_break:n { \includegraphics[#1]{##1#2} }
     }
   }
 }
\bool_new:N \l__psychonaut_file_exist_bool
\prg_new_conditional:Nnn \_psychonaut_file_if_exist:n { T }
 {
  \bool_set_false:N \l__psychonaut_file_exist_bool
  \clist_map_inline:cn { Gin@extensions }
   {
    \file_if_exist:nT { #1##1 }
     {
      \clist_map_break:n { \bool_set_true:N \l__psychonaut_file_exist_bool }
     }
   }
  \bool_if:NTF \l__psychonaut_file_exist_bool
   {
    \prg_return_true:
   }
   {
    \prg_return_false:
   }
 }

\AtBeginDocument
 {
  \tl_if_exist:cF { Ginput@path } { \tl_new:c { Ginput@path } }
  \tl_put_right:cn { Ginput@path } { {} }
 }
\ExplSyntaxOff

\graphicspath{{images/}}

\begin{document}

\slowincludegraphics[width=\linewidth]{cc-by-sa}

\end{document}

答案2

情况类似于输入 TeX 文件(因为它使用相同的机制来查找文件)

如果在文件名前面加上,./则它只会在使用图形路径之前在当前目录中查找

\documentclass{article}

\usepackage{graphicx}

\graphicspath{{images/}}

\begin{document}

%known name clash with image in input path
\includegraphics{./example-image}

\end{document}

如果images包含一个图像(也)称为example-image.png那么你得到

<images/./example-image.png, id=1, 401.5pt x 301.125pt>
<use images/./example-image.png>

所以使用本地的。

如果你使用

\includegraphics{example-image}

然后日志显示

<example-image.png, id=1, 401.5pt x 301.125pt> <use example-image.png>

事实上,这里的一个

$ kpsewhich example-image.png
/usr/local/texlive/2015/texmf-dist/tex/latex/mwe/example-image.png

图形包无法明确说明与 TEXINPUTS 的交互,因为在编写它时(主要是 1993 年),并非所有 TeX 系统都具有 TEXINPUTS,而那些拥有 TEXINPUTS 的系统并不都以相同的方式使用该变量。(这就是为什么 LaTeX 有 TEXINPUTS \input@path,以允许在没有内置路径搜索的系统上搜索包文件,它只是被重新用于图形......)

相关内容