Is it possible to "relocate" my ~/texmf/ directory?
If you issue the shell command
cat $(kpsewhich texmf.cnf)
(bash
syntax, adapt to your shell way to do command substitution) you should see
% (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
(this is what you get on standard Unix boxes, there is /Library
after ~
with the MacTeX version of TeX Live).
If the start of the file you get is different, namely
% original texmf.cnf -- runtime path configuration file for kpathsea.
then your system doesn't have a top level texmf.cnf
file. No problem.
All it takes is to launch
sudo nano $(kpsewhich -var-value TEXMFROOT)/texmf.cnf
(use whatever method you use for getting superuser privileges and whatever editor you prefer). If you are in the no-top-level-texmf.cnf
situation, you will see an empty file.
Add or change the TEXMFHOME
line to what you wish. Perhaps also the other lines, if you also want to move texlive
to a hidden place.
Then rename or move the relevant directories to the correct place.
Explanation. The file resides at the top level of the TeX Live distribution, namely at
/usr/local/texlive/2018/texmf.cnf
and it is the first configuration file read by kpse
library linked programs (all those in the TeX family); other files with the same name are read in during initialization, but values of (pseudo)enviroment variables are never overridden by subsequent files. Setting personal preferences in that file is actually the recommended method.
I had written most of this answer more or less a month ago, but I hadn’t found the time to complete it until now.
Shorter Answer
Elaborating on what I’ve already said in a comment, in my humble opinion the best way to achieve literally what the question asks for depends on whether you are a generic, unprivileged user trying to relocate just your own ~/texmf/
directory, or an administrator who wants to set a different location for the ~/texmf/
directory of all users of a given host.
Generic user who wants to relocate only her/his own directory
Add a line to your .profile
, .bashrc
, or whatever configuration file your shells reads during initialization a line that creates an environment variable (not just a shell variable) named TEXMFHOME
and sets its value to the path that should be used instead of ~/texmf
. For example, for a Bourne shell you might add to your .bashrc
file a line that says
export TEXMFHOME='~/.some/hidden/place/texmf'
(note that quoting has been used to prevent tilde expansion from being applied by the shell itself).
Administrator who wants to relocate all users’ directories
Let’s assume that your TeX Live distribution for 2018 is located in
/some/path/to/texlive/2018
which amounts to saying that the above path is what you get in reply to the command
kpsewhich -var-value TEXMFROOT
(normally, the reply to this command will be
/usr/local/texlive/2018
which amounts to saying that the above path is where TeX Live 2018 is normally installed on Unix-like systems); then, the parent directory
/some/path/to/texlive
is likely to contain other subdirectories, one for each distribution of a previous year you are still retaining, plus one additional subdirectory named texmf-local
(for example, on my machine, the directory
/usr/local/texlive
contains the following subdirectories
2014/
2015/
2016/
2017/
2018/
texmf-local/
with old distributions going back to that of 2014). In any case, acquire root privileges and create a (text) file with full pathname
/some/path/to/texlive/texmf-local/web2c/texmf.cnf
also creating, if necessary, any missing directory along the path (for example, on the machine I’m using now I’d create a file with full pathname
/usr/local/texlive/texmf-local/web2c/texmf.cnf
but on some other machine of mine I wouldn’t need to, because I already did so a few years ago). Open that file for editing and write the following line into it:
TEXMFHOME = ~/.some/hidden/place/texmf
Save the file. That’s all: TeX Live will now look inside ~/.some/hidden/place/texmf/
(and the sub-sub-…-directories thereof) for anything it would have previously searched inside ~/texmf/
(and the sub-sub-…-directories thereof). Don’t forget to instruct users to move their personal texmf tree in the new location!
Comments and caveats
Following this strategy, you won’t need to reapply your customization every time you switch to a new distribution—that is, every year—which, as I remarked in a comment, is a small drawback of the other answer. Indeed, you might want to add other lines to your new file
/some/path/to/texlive/texmf-local/web2c/texmf.cnf
in order to specify some other customization you want to apply on a “all-user, all-year” basis; for example, on some machines (not on this one) I keep, as I’ve already said, a file
/usr/local/texlive/texmf-local/web2c/texmf.cnf
which contains the line
file_line_error_style = t
(possibly among others).
This strategy too, however, is not immune from defects, which are discussed in the longer answer that follows.
Longer Answer (and Explanation)
The path to the root of the “personal” texmf tree, or, more precisely, the value of TEXMFHOME
, is specified (of course!) in the same way as any other path, that is, as documented in the Kpathsea manual, Section 5.2 Path Sources, by looking it up in the following sources of information:
A user-set environment variable, e.g.,
TEXINPUTS
. Environment variables with an underscore and the program name appended override; for example,TEXINPUTS_latex
overridesTEXINPUTS
if the program being run is namedlatex
.A program-specific configuration file, e.g., an
S /a:/b
line in Dvips’config.ps
(see Config files in Dvips).A line in a Kpathsea configuration file texmf.cnf, e.g.,
TEXINPUTS=/c:/d
(see below).The compile-time default (specified in
kpathsea/paths.h
).
These sources are queried in turn, in the stated order, and earlier definitions override later ones; moreover, a higher-priority source can “import” a lower-priority one via a mechanism known as “Default Expansion”, which we are not going to describe here (interested readers are referred to Subsection 5.3.1 Default Expansion of the above-cited manual)
Given the above information, you may think that the easiest way to achieve what the question asks for is, perhaps, to set (and export) an environment variable named TEXMFHOME
in your .profile
/.bashrc
/etc. file. There are some caveats, though:
The configuration files in the TeX Live distribution define a few other path variables that should be kept “in sync” with
TEXMFHOME
, but that, notwithstanding this, are not defined in terms of the latter; for example, on my machine (a Mac with MacTeX installed), the file located at/usr/local/texlive/2018/texmf.cnf
reads as follows:
% (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
Obviously,
TEXMFVAR
andTEXMFCONFIG
should be kept “synchronized” withTEXMFHOME
. (At this point, the attentive and knowledgeable reader has probably already spotted the source of the trouble…)You might want to consider quoting the values assigned to environmental variables within a shell script in order to prevent premature expansion by the shell itself.
Following this line of thought, the next option is, of course, to have the desired value of the TEXMFHOME
(and, one might feel inclined to add, of the other “synchronized” variables, TEXMFVAR
and TEXMFCONFIG
) specified in a configuration file, which, in this case, can only be one of the several texmf.cnf
files. We say “the several” because the Kpathsea library can read more than one such file, and actually does so in typical situations. Quoting from Subsection 5.2.1 Config files of the manual,
[…] Kpathsea reads runtime configuration files named
texmf.cnf
for search path and other definitions. The search path used to look for these configuration files is namedTEXMFCNF
, and is constructed in the usual way, as described above [items 1–4], except that configuration files cannot be used to define the path, naturally; also, anls-R
database is not used to search for them.Kpathsea reads all
texmf.cnf
files in the search path, not just the first one found; definitions in earlier files override those in later files. […]
In practice, the first of the two paragraphs just quoted means that TEXMFCNF
(which, we repeat, is the search path for the configuration files themselves) is defined either in an environmental variable, or by the compile-time default. Let the former alternative alone, and let’s concentrate on the search path specified at compile-time: as the manual says, this is defined in kpathsea/paths.h
; inspecting that file, we find that the definition of DEFAULT_TEXMFCNF
reads (I’ve broken it up into separate lines for readability):
#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
Indeed, this corresponds exactly to what I get on my machine if I issue the shell command
kpsewhich -var-value TEXMFCNF
The answer I get is (again, split up into lines for readability):
{/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}
Let’s spend a couple of minutes to understand exactly why the above two listings agree, because something important is involved here.
First of all, I haven’t set TEXMFCNF
in my environment, so what I’m getting is indeed the compile-time default. (Note: As a matter of fact, this is not true, because the main texmf.cnf
file of TeX Live, that is, /usr/local/texlive/2018/texmf-dist/web2c/texmf.cnf
, actually redefines the TEXMFCNF
variable; but it is a white lie, since this redefinition agrees completely with the compile-time default.) That being said, the key point is to understand how the (pseudo-?) variables SELFAUTOLOC
, SELFAUTODIR
, SELFAUTOPARENT
, and SELFAUTOGRANDPARENT
are interpreted; their meaning is always relative to the position of the executable file that has invoked the Kpathsea library (e.g., pdftex
, pdflatex
, tex
, but also kpsewhich
); more precisley:
SELFAUTOLOC
expands to the path to the directory that contains the executable;SELFAUTODIR
expands to the parent directory of the directory that contains the executable;SELFAUTOPARENT
expands to the parent directory of the parent directory of the directory that contains the executable;SELFAUTOGRANDPARENT
expands to the parent directory of the parent directory of the parent directory of the directory that contains the executable.
A bit confusing, isn’t it? It’s better to use an example: let’s say that the executable file resides inside
/usr/local/texlive/2018/bin/x86_64-darwin/
(as it is on my machine); then:
SELFAUTOLOC
expands to/usr/local/texlive/2018/bin/x86_64-darwin
SELFAUTODIR
expands to/usr/local/texlive/2018/bin
SELFAUTOPARENT
expands to/usr/local/texlive/2018
SELFAUTOGRANDPARENT
expands to/usr/local/texlive
(Much clearer, I’d say.) You can now return to the two listings given above, and amuse yourself by checking that each line of the first expands precisely to its corresponding line in the second.
Note an important detail: being relative to the location of the executable, the above expansions work correctly even if the whole texmf tree is moved to a different location (perhaps on a removable media, like a USB stick).
Armed with this knowledge, let’s focus on the particular use that the TeX Live distribution makes of all this machinery. Usually, only two items of the compile-time default are exploited by TeX Live, namely
$SELFAUTOPARENT
and
$SELFAUTOPARENT/texmf-dist/web2c
The latter is the “original” texmf.cnf
file being distributed; the former (that, remember, takes precedence) is provided to allow host-specific customization. By way of example, the MacTeX distribution uses the $SELFAUTOPARENT
entry to customize the location of the personal texmf tree (TEXMFHOME
), moving it inside the Library/
subdirectory of the user’s home folder. This may make this file look like the natural place to turn to in order to solve the OP’s problem, as @egreg has already suggested; but there are a couple of issues you should be aware of:
This solution (as any other based on configuration files) applies on a per-host basis, that is, to all users of a given machine.
Because
SELFAUTOPARENT
expands to a directory name that embodies the year of the distribution, you’ll need to re-apply your customization when you update your distribution: indeed, in a new distribution the location of the executable will change, and, with it, the value ofSELFAUTOPARENT
.
Point 1 can be a problem or a feature, depending on the circumstances. As for point 2, a remedy is—or seems to be—readily available: if you go back to the listings extracted from kpathsea/paths.h
, you’ll notice, among the entries that precede the two ones used by TeX Live, one that looks particularly appealing:
$SELFAUTOGRANDPARENT/texmf-local/web2c
which typically expands to
/usr/local/texlive/texmf-local/web2c
(“Aha!”—you might be thinking); and indeed, this is where, sometimes (that is, on some machines, but not on this particular one), I keep a third texmf.cnf
file, containing the patches I want to apply on a “per-host, but all-year” basis. Well, if you create a file in this location, that is, having full pathname
/usr/local/texlive/texmf-local/web2c/texmf.cnf
and whose contents look like this
TEXMFHOME = ~/.SomeHiddenPlace/texmf
you are changing, in the stated way, the location of the personal texmf tree of all users on your machine, and this change will be permanent across distributions. This is exactly what the title of the question asks for; however, an issue remains, that we have already touched upon above, and that proves unexpectedly difficult to solve, in full generality, by similar means.
We already remarked that there are (at least) two other paths into the personal tree that one would reasonably want to keep “synchronized” with TEXMFHOME
, those corresponding to the two variables TEXMFVAR
and TEXMFCONFIG
. Their default definition (i.e., their definition in the “original” texmf.cnf
file of TeX Live) is
% 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
It seems reasonable that, if one wishes to convert
TEXMFHOME = ~/texmf
into
TEXMFHOME = ~/.SomeHiddenPlace/texmf
in the same way the same person might want to have TEXMFVAR
and TEXMFCONFIG
moved in parallel, in order to reduce clutter in her/his home directory:
TEXMFVAR = ~/.SomeHiddenPlace/.texlive2018/texmf-var
TEXMFCONFIG = ~/.SomeHiddenPlace/.texlive2018/texmf-config
In the same way, under MacTeX, one might want to pass from
TEXMFHOME = ~/Library/texmf
TEXMFVAR = ~/Library/texlive/2018/texmf-var
TEXMFCONFIG = ~/Library/texlive/2018/texmf-config
to, say,
TEXMFHOME = ~/Library/TeXStuff/texmf
TEXMFVAR = ~/Library/TeXStuff/texlive/2018/texmf-var
TEXMFCONFIG = ~/Library/TeXStuff/texlive/2018/texmf-config
(although the motivation is much weaker in this case). The problem is that the last two directories should be kept separate in passing from one year to the next; for example, both occurences of 2018
, above, should be replaced by 2019
when the 2019 distribution of TeX Live becomes available.
A modest proposal
A possible solution would be to define, in the texmf.cnf
file distributed with TeX Live, a new variable that holds the year of the distribution. Let’s assume that this variable is called YYYY
; then we could write something like
TEXMFHOME = ~/.SomeHiddenPlace/texmf
TEXMFVAR = ~/.SomeHiddenPlace/.texlive${YYYY}/texmf-var
TEXMFCONFIG = ~/.SomeHiddenPlace/.texlive${YYYY}/texmf-config
in the file
$SELFAUTOGRANDPARENT/texmf-local/web2c
(the typical expansion of which is
/usr/local/texlive/texmf-local/web2c
that is, the file you need not modify when you upgrade your TeX Live distribution to that of a new year) to move the specified directories under .SomeHiddenPlace/
for all the users and all the years to come. Note that this works correctly even if the file that defines the YYYY
variable is read by the Kpathsea library after the file where that variable is used; indeed, quoting from Section 5.2.1 of the Kpathsea manual:
All definitions are read before anything is expanded, so you can use variables before they are defined (like Make, unlike most other programs).
The TeX Live team might want to give this proposal some thought.