对于包含大量插图的大型文档,我通常的做法是将图形文件组织到一个或多个子目录中,然后将这些子目录添加到图形路径中,以便\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
,以允许在没有内置路径搜索的系统上搜索包文件,它只是被重新用于图形......)