简短答案

简短答案

我的自定义sty文件存储在~/texmf/目录中。我希望主目录的内容保持简单,所以我想移动到~/texmf/其他地方(可能~/.texmf/~/.config/texmf/)。这可能吗?

答案1

如果你发出 shell 命令

cat $(kpsewhich texmf.cnf)

bash语法,适应你的 shell 方式来做命令替换)你应该看到

% (Public domain.)
% This texmf.cnf file should contain only your personal changes from the
% original texmf.cnf (for example, as chosen in the installer).
%
% That is, if you need to make changes to texmf.cnf, put your custom
% settings in this file, which is .../texlive/YYYY/texmf.cnf, rather than
% the distributed file (which is .../texlive/YYYY/texmf-dist/web2c/texmf.cnf).
% And include *only* your changed values, not a copy of the whole thing!
%
TEXMFHOME = ~/texmf
TEXMFVAR = ~/texlive/2018/texmf-var
TEXMFCONFIG = ~/texlive/2018/texmf-config

(这是您在标准 Unix 机器上所得到的,之后是/LibraryMacTeX~版本的 TeX Live)。

如果你得到的文件的开头不同,即

% original texmf.cnf -- runtime path configuration file for kpathsea.

那么你的系统就没有顶层texmf.cnf文件。没问题。

只需启动

sudo nano $(kpsewhich -var-value TEXMFROOT)/texmf.cnf 

(使用您获取超级用户权限的任何方法和您喜欢的任何编辑器)。如果您处于无顶层的texmf.cnf情况,您将看到一个空文件。

根据你的需要添加或更改线路TEXMFHOME。如果你还想移动texlive到隐藏位置,也可以添加其他线路。

然后重命名或移动相关目录到正确的位置。

解释。该文件位于 TeX Live 发行版的顶层,即

/usr/local/texlive/2018/texmf.cnf

它是库链接程序(所有 TeX 系列程序)读取的第一个配置文件kpse;在初始化期间会读取其他同名文件,但(伪)环境变量的值永远不会被后续文件覆盖。在该文件中设置个人偏好实际上是推荐的方法。

答案2

我大约一个月前就已经写完了这个答案的大部分内容,但直到现在我才有时间将其完成。


简短答案

详细阐述我在一条评论,以我的拙见,实现问题所要求的最佳方式取决于您是试图重新定位您自己的~/texmf/目录的普通、非特权用户,还是想要为给~/texmf/定主机的所有用户的目录设置不同位置的管理员。

只想重新定位自己目录的普通用户

.profile在你的、或者你的 shell 在初始化期间读取的任何配置文件中添加一行.bashrc,创建一个环境变量(不仅仅是 shell 变量)命名TEXMFHOME并将其值设置为应该使用的路径,而不是~/texmf。例如,对于 Bourne shell,您可以在文件中添加.bashrc一行,内容如下:

export TEXMFHOME='~/.some/hidden/place/texmf'

(请注意,使用引号是为了防止 shell 本身应用波浪符号扩展)。

想要重新定位所有用户目录的管理员

假设你的 TeX Live 2018 发行版位于

/some/path/to/texlive/2018

这相当于说上述路径就是你对命令的回复

kpsewhich -var-value TEXMFROOT

(通常,此命令的回复将是

/usr/local/texlive/2018

也就是说,上面的路径是 TeX Live 2018 在类 Unix 系统上的正常安装位置);然后是父目录

/some/path/to/texlive

可能包含其他子目录,每个子目录对应您仍保留的前一年发行版,以及一个名为的附加子目录texmf-local(例如,在我的计算机上,目录

/usr/local/texlive

包含以下子目录

2014/
2015/
2016/
2017/
2018/
texmf-local/

旧发行版可追溯到 2014 年)。无论如何,获取 root 权限并创建一个具有完整路径名的(文本)文件

/some/path/to/texlive/texmf-local/web2c/texmf.cnf

如果有必要,还可以创建路径上任何缺失的目录(例如,在我现在使用的机器上,我会创建一个具有完整路径名的文件

/usr/local/texlive/texmf-local/web2c/texmf.cnf

但在我的其他机器上则不需要,因为我几年前就已经这么做了。打开该文件进行编辑,并将以下行写入其中:

TEXMFHOME = ~/.some/hidden/place/texmf

保存文件。就这样:TeX Live 现在将在内部~/.some/hidden/place/texmf/(及其子子目录)查找它之前在其中搜索过的内容~/texmf/(及其子子目录)。别忘了指示用户将他们的个人 texmf 树移动到新位置!

评论和警告

按照这个策略,你不需要在每次切换到新的发行版时(也就是每年)重新应用你的自定义设置,正如我在一条评论,是另一个答案的一个小缺点。事实上,你可能想在新文件中添加其他行

/some/path/to/texlive/texmf-local/web2c/texmf.cnf

为了指定您想要在“所有用户、全年”基础上应用的一些其他自定义设置;例如,在某些机器上(不是在这台机器上),正如我已经说过的,我保留了一个文件

/usr/local/texlive/texmf-local/web2c/texmf.cnf

其中包含以下行

file_line_error_style = t

(可能还包括其他人)。

但是,这种策略也并非没有缺陷,我们将在后面的详细解答中讨论这些缺陷。


详细答案(及解释)

“个人” texmf 树根的路径,或者更准确地说,的值TEXMFHOME,以与任何其他路径相同的方式指定(当然!),即如Kpathsea 手册, 部分5.2 路径来源,请查阅以下信息来源:

  1. 用户设置的环境变量,例如TEXINPUTS。带有下划线和附加程序名称的环境变量将覆盖;例如, 如果正在运行的程序名为 ,TEXINPUTS_latex则会覆盖。TEXINPUTSlatex

  2. 特定于程序的配置文件,例如S /a:/bDvips 中的一行config.ps(请参阅 Dvips 中的配置文件)。

  3. Kpathsea 配置文件 texmf.cnf 中的一行,例如 TEXINPUTS=/c:/d(见下文)。

  4. 编译时默认值(在 中指定kpathsea/paths.h)。

这些源按规定的顺序依次查询,较早的定义将覆盖较晚的定义;此外,较高优先级的源可以通过称为“默认扩展”的机制“导入”较低优先级的源,我们在此不做描述(感兴趣的读者请参阅第 5.3.1 默认扩展上述手册)

鉴于以上信息,您可能会认为实现问题要求的最简单方法可能是设置(并导出)/ /etc. 文件TEXMFHOME中命名的环境变量。不过,有一些注意事项:.profile.bashrc

  • TeX Live 发行版中的配置文件定义了一些其他路径变量,这些变量应与 保持“同步” TEXMFHOME,但尽管如此,它们并没有根据后者进行定义;例如,在我的计算机上(安装了 MacTeX 的 Mac),位于

    /usr/local/texlive/2018/texmf.cnf
    

    内容如下:

    % (Public domain.)
    % This texmf.cnf file should contain only your personal changes from the
    % original texmf.cnf (for example, as chosen in the installer).
    %
    % That is, if you need to make changes to texmf.cnf, put your custom
    % settings in this file, which is .../texlive/YYYY/texmf.cnf, rather than
    % the distributed file (which is .../texlive/YYYY/texmf-dist/web2c/texmf.cnf).
    % And include *only* your changed values, not a copy of the whole thing!
    %
    TEXMFHOME = ~/Library/texmf
    TEXMFVAR = ~/Library/texlive/2018/texmf-var
    TEXMFCONFIG = ~/Library/texlive/2018/texmf-config
    

    显然,TEXMFVARTEXMFCONFIG应该与 保持“同步” TEXMFHOME。 (此时,细心且知识渊博的读者可能已经发现了问题的根源……)

  • 您可能需要考虑在 shell 脚本中引用分配给环境变量的值,以防止 shell 本身过早扩展。

按照这种思路,下一个选项当然是将所需的值TEXMFHOME(以及,有人可能倾向于添加,其他“同步”变量TEXMFVARTEXMFCONFIG)指定在配置文件中,在本例中,该文件只能是几个texmf.cnf文件之一。我们说“几个”,因为 Kpathsea 库可以读取多个这样的文件,并且在典型情况下确实如此。引用自子节 5.2.1 配置文件本手册,

[…] Kpathsea 阅读运行时配置文件命名texmf.cnf 用于搜索路径和其他定义。用于查找这些配置文件的搜索路径名为TEXMFCNF,并以通常的方式构造,如上所述[第 1-4 项],只是配置文件不能用于定义路径,这是自然的;而且,ls-R不使用数据库来搜索它们。

Kpathsea 阅读全部 texmf.cnf搜索路径中的文件,而不仅仅是找到的第一个文件;较早文件中的定义会覆盖较晚文件中的定义。[…]

实际上,刚刚引用的两段中的第一段意味着TEXMFCNF(我们重复一遍,这是配置文件本身的搜索路径)要么在环境变量中定义,要么由编译时默认值定义。先不管前一种选择,让我们集中精力讨论编译时指定的搜索路径:正如手册所说,这是在kpathsea/paths.h;检查该文件,我们发现读取的定义DEFAULT_TEXMFCNF(为了便于阅读,我将其分成单独的行):

#ifndef DEFAULT_TEXMFCNF
#define DEFAULT_TEXMFCNF "{$SELFAUTOLOC,\
  $SELFAUTOLOC/share/texmf-local/web2c,\
  $SELFAUTOLOC/share/texmf-dist/web2c,\
  $SELFAUTOLOC/share/texmf/web2c,\
  $SELFAUTOLOC/texmf-local/web2c,\
  $SELFAUTOLOC/texmf-dist/web2c,\
  $SELFAUTOLOC/texmf/web2c,\
  $SELFAUTODIR,\
  $SELFAUTODIR/share/texmf-local/web2c,\
  $SELFAUTODIR/share/texmf-dist/web2c,\
  $SELFAUTODIR/share/texmf/web2c,\
  $SELFAUTODIR/texmf-local/web2c,\
  $SELFAUTODIR/texmf-dist/web2c,\
  $SELFAUTODIR/texmf/web2c,\
  $SELFAUTOGRANDPARENT/texmf-local/web2c,\
  $SELFAUTOPARENT,\
  $SELFAUTOPARENT/share/texmf-local/web2c,\
  $SELFAUTOPARENT/share/texmf-dist/web2c,\
  $SELFAUTOPARENT/share/texmf/web2c,\
  $SELFAUTOPARENT/texmf-local/web2c,\
  $SELFAUTOPARENT/texmf-dist/web2c,\
  $SELFAUTOPARENT/texmf/web2c}"
#endif

事实上,这与我在机器上执行 shell 命令时得到的结果完全一致

kpsewhich -var-value TEXMFCNF

我得到的答案是(再次分成几行以便于阅读):

{/usr/local/texlive/2018/bin/x86_64-darwin,
  /usr/local/texlive/2018/bin/x86_64-darwin/share/texmf-local/web2c,
  /usr/local/texlive/2018/bin/x86_64-darwin/share/texmf-dist/web2c,
  /usr/local/texlive/2018/bin/x86_64-darwin/share/texmf/web2c,
  /usr/local/texlive/2018/bin/x86_64-darwin/texmf-local/web2c,
  /usr/local/texlive/2018/bin/x86_64-darwin/texmf-dist/web2c,
  /usr/local/texlive/2018/bin/x86_64-darwin/texmf/web2c,
  /usr/local/texlive/2018/bin,
  /usr/local/texlive/2018/bin/share/texmf-local/web2c,
  /usr/local/texlive/2018/bin/share/texmf-dist/web2c,
  /usr/local/texlive/2018/bin/share/texmf/web2c,
  /usr/local/texlive/2018/bin/texmf-local/web2c,
  /usr/local/texlive/2018/bin/texmf-dist/web2c,
  /usr/local/texlive/2018/bin/texmf/web2c,
  /usr/local/texlive/texmf-local/web2c,
  /usr/local/texlive/2018,
  /usr/local/texlive/2018/share/texmf-local/web2c,
  /usr/local/texlive/2018/share/texmf-dist/web2c,
  /usr/local/texlive/2018/share/texmf/web2c,
  /usr/local/texlive/2018/texmf-local/web2c,
  /usr/local/texlive/2018/texmf-dist/web2c,
  /usr/local/texlive/2018/texmf/web2c}

让我们花几分钟来准确理解一下为什么以上两个列表一致,因为这里涉及到一些重要的事情。

首先,我没有TEXMFCNF在我的环境中进行设置,所以我得到的确实是编译时默认值。(笔记:事实上,这是不正确的,因为texmf.cnfTeX Live 的主文件,也就是,/usr/local/texlive/2018/texmf-dist/web2c/texmf.cnf实际上重新定义变量TEXMFCNF;但这是一个善意的谎言,因为这个重新定义完全符合编译时默认值。)话虽如此,关键是要理解(伪?)变量SELFAUTOLOCSELFAUTODIRSELFAUTOPARENTSELFAUTOGRANDPARENT是如何解释的;它们的含义始终相对于调用 Kpathsea 库的可执行文件的位置(例如,,,,而且);更准确地说pdftexpdflatextexkpsewhich

  • SELFAUTOLOC扩展为包含可执行文件的目录的路径;

  • SELFAUTODIR扩展到包含可执行文件的目录的父目录;

  • SELFAUTOPARENT扩展到包含可执行文件的目录的父目录的父目录;

  • SELFAUTOGRANDPARENT扩展到包含可执行文件的目录的父目录的父目录的父目录。

有点令人困惑,不是吗?最好使用一个例子:假设可执行文件位于

/usr/local/texlive/2018/bin/x86_64-darwin/

(就像在我的计算机上一样);然后:

  • SELFAUTOLOC扩展为

    /usr/local/texlive/2018/bin/x86_64-darwin
    
  • SELFAUTODIR扩展为

    /usr/local/texlive/2018/bin
    
  • SELFAUTOPARENT扩展为

    /usr/local/texlive/2018
    
  • SELFAUTOGRANDPARENT扩展为

    /usr/local/texlive
    

(我想说,这样更清楚。)现在,您可以返回到上面给出的两个清单,并通过检查第一个清单中的每一行是否精确扩展到第二个清单中相应的行来获得乐趣。

请注意一个重要细节:相对于可执行文件的位置,即使整个 texmf 树被移动到其他位置(可能是在可移动介质上,例如 USB 记忆棒),上述扩展也能正常工作。

有了这些知识,让我们关注一下 TeX Live 发行版对这些机制的具体用途。通常,TeX Live 只利用编译时默认值中的两项,即

$SELFAUTOPARENT

$SELFAUTOPARENT/texmf-dist/web2c

后者是texmf.cnf分发的“原始”文件;前者(请记住,优先)用于允许特定于主机的自定义。例如,MacTeX 发行版使用条目$SELFAUTOPARENT来自定义个人 texmf 树的位置(TEXMFHOME),将其移动到用户主文件夹的子目录中Library/。这可能使该文件看起来像是解决 OP 问题的自然选择,正如@egreg 所说已经建议;但您应该注意以下几个问题:

  1. 此解决方案(与任何其他基于配置文件的解决方案一样)适用于每个主机,即全部给定机器的用户。

  2. 因为SELFAUTOPARENT扩展为体现发行年份的目录名,所以当您更新发行版时,您需要重新应用您的自定义:事实上,在新的发行版中,可执行文件的位置将会改变,并且 的值也会随之改变SELFAUTOPARENT

第 1 点可能是问题,也可能是功能,具体取决于具体情况。至于第 2 点,补救措施是——或者似乎随时可用:如果你回到从中提取的列表kpathsea/paths.h,你会注意到,在 TeX Live 使用的两个条目之前的条目中,有一个看起来特别有吸引力:

$SELFAUTOGRANDPARENT/texmf-local/web2c

通常会扩展为

/usr/local/texlive/texmf-local/web2c

(“啊哈!”——你可能会想);事实上,这就是我有时(在某些机器上,但不在这台特定的机器上)保存第三 texmf.cnf文件,其中包含我想要“按主机、但全年”应用的补丁。好吧,如果您在此位置创建一个文件,即具有完整路径名

/usr/local/texlive/texmf-local/web2c/texmf.cnf

其内容如下

TEXMFHOME = ~/.SomeHiddenPlace/texmf

您正在以所述方式更改计算机上所有用户的个人 texmf 树的位置,并且此更改将在各个发行版中永久生效。这正是标题问题所要求的;然而,仍然存在一个问题,我们上面已经提到过,并且事实证明,通过类似的方法完全普遍地解决这个问题出乎意料地困难。

我们已经指出,个人树中至少还有两条路径,人们有理由希望与 保持“同步” TEXMFHOME,它们对应于两个变量TEXMFVARTEXMFCONFIG。它们的默认定义 (IEtexmf.cnf,它们在TeX Live 的“原始”文件中的定义是

% TEXMFVAR, where texconfig/updmap/fmtutil store cached runtime data.
TEXMFVAR = ~/.texlive2018/texmf-var

% TEXMFCONFIG, where texconfig/updmap/fmtutil store configuration data.
TEXMFCONFIG = ~/.texlive2018/texmf-config

如果有人想转换

TEXMFHOME = ~/texmf

进入

TEXMFHOME = ~/.SomeHiddenPlace/texmf

以同样的方式,同一个人可能希望同时拥有TEXMFVARTEXMFCONFIG移动,以减少他/她的主目录中的混乱:

TEXMFVAR = ~/.SomeHiddenPlace/.texlive2018/texmf-var
TEXMFCONFIG = ~/.SomeHiddenPlace/.texlive2018/texmf-config

同样,在 MacTeX 下,人们可能希望从

TEXMFHOME = ~/Library/texmf
TEXMFVAR = ~/Library/texlive/2018/texmf-var
TEXMFCONFIG = ~/Library/texlive/2018/texmf-config

比如说,

TEXMFHOME = ~/Library/TeXStuff/texmf
TEXMFVAR = ~/Library/TeXStuff/texlive/2018/texmf-var
TEXMFCONFIG = ~/Library/TeXStuff/texlive/2018/texmf-config

(尽管在这种情况下动机要弱得多)。问题是,最后两个目录在从一年到下一年的过程中应该分开;例如,2018上面的两个 都应该替换为20192019 年 TeX Live 发行版可用时。

一个温和的建议

一种可能的解决方案是在 TeX Live 分发的文件中定义texmf.cnf一个新变量,用于保存分发的年份。假设这个变量名为YYYY;那么我们可以编写类似

TEXMFHOME = ~/.SomeHiddenPlace/texmf
TEXMFVAR = ~/.SomeHiddenPlace/.texlive${YYYY}/texmf-var
TEXMFCONFIG = ~/.SomeHiddenPlace/.texlive${YYYY}/texmf-config

在文件中

$SELFAUTOGRANDPARENT/texmf-local/web2c

(其典型扩展是

/usr/local/texlive/texmf-local/web2c

即,将 TeX Live 发行版升级到新一年的版本时不需要修改的文件)将指定的目录移动到所有用户和所有年份下。请注意,即使定义变量的文件由 Kpathsea 库读取,.SomeHiddenPlace/此方法也能正常工作YYYY使用该变量的文件;事实上,引用自第 5.2.1 节Kpathsea 手册

在扩展任何内容之前,所有定义都会被读取,因此您可以在定义变量之前使用它们(与 Make 类似,与大多数其他程序不同)。

TeX Live 团队可能需要考虑一下这个提议。

相关内容