TeX のディレクトリ構成とパス

TeX のインストールは、数万個のファイル — マクロ、クラス、フォント、設定 — の集まりです。なぜ \usepackage{amsmath} と一行書くだけで、ディスクのどこかにある amsmath.sty が見つかるのか。その裏には、ファイルの 置き場所の標準(TDS) と、それを 探し出す仕組み(kpathsea) という二つの約束があります。このページは、その地図を描くことが目的です。

TDS — ファイルの置き場所の標準

すべての出発点は texmf ツリー と呼ばれるディレクトリの木です。「texmf」は *TeX and Metafont* の頭文字。その下は、ファイルの 種類ごと に枝分かれします。マクロやクラスは tex/、フォント関係は fonts/、文献データは bibtex/、文書(マニュアル)は doc/、スクリプトは scripts/ といった具合です。この並べ方を全世界で統一したのが TDS(TeX Directory Structure) で、TeX ユーザー会(TUG)が 1990 年代に定めました。

なぜ標準が要るのか。TeX は MacOS・Unix・Windows と多くの環境で動き、CTAN(包括的 TeX アーカイブ網)には膨大なパッケージが集まります。置き場所がばらばらだと、パッケージを配る側も探す側も毎回つまずきます。「tex/ の下を見ればマクロがある」と決まっていれば、どの OS でも、どのディストリビューションでも、ファイルの在処を 規則だけで 推測できます。TDS が解決するのは、まさにこの 移植性 の問題です。

枝の下にはさらに規則があります。tex/フォーマット別・パッケージ別 に分かれ、tex/<format>/<package>/ という形になります(<format>latexplaingeneric など)。たとえば標準クラスの article.cls は次の場所にあります。実際にお使いの環境でも、後で出てくる kpsewhich で同じ場所が返ってくるはずです。

terminal
$ kpsewhich article.cls
/usr/local/texlive/2026/texmf-dist/tex/latex/base/article.cls

フォントはもう一段細かく、fonts/<type>/<supplier>/<typeface>/ と並びます。<type> はファイルの種別で、TeX 用メトリックの tfm、仮想フォントの vftype1opentypetruetype など。<supplier> は供給元(publicadobeams など)、<typeface> は書体名(cm=Computer Modern など)です。下表は、よく出会う枝とその役割です。

ディレクトリ中身
tex/マクロ・クラス・スタイル(.tex .sty .cls)。tex/latex/... など
fonts/フォント一式。tfmvftype1opentypeencmap など種別ごと
bibtex/文献データベース bib/ とスタイル bst/
doc/パッケージの説明書・マニュアル(texdoc が開く先)
scripts/OS 非依存の実行スクリプト(mktexlsr などの本体)
web2c/エンジンの設定。texmf.cnf やフォーマット定義が住む

複数のツリーと、その優先順位

texmf ツリーは 一つではありません。TeX Live は役割の違う複数のツリーを束ねて使い、それぞれに TEXMF… という環境変数名が付いています。なぜ分けるのか。配布物(読み取り専用で、更新のたびに丸ごと入れ替わる) と、あなたが足したもの(消えては困る) と、自動生成される作業用データ を混ぜないためです。混在していると、ディストリビューションを更新した瞬間に自作のスタイルが消し飛びかねません。

変数役割と既定の場所(例: TeX Live 2026)
TEXMFDIST配布物の本体。膨大なパッケージはここ。触らない.../texlive/2026/texmf-dist
TEXMFLOCALサイト全体への追加(全ユーザー共有)。.../texlive/texmf-local
TEXMFHOME自分専用のツリー。個人のスタイルや自作クラスはここ。~/texmf(Mac は ~/Library/texmf
TEXMFVAR自動生成のキャッシュ(フォーマット・フォントなど)。手で編集しない
TEXMFCONFIGユーザー単位の設定の置き場(updmap 等が書き込む)
TEXMFSYSVAR / SYSCONFIG上記 VAR/CONFIG のシステム全体版
TEXMFROOTインストール全体の根。.../texlive/2026

同じ名前のファイルが複数のツリーにあったら、どれが使われるのか。これを決めるのが変数 TEXMF で、探索の 優先順位 をそのまま並べたものです。実際に問い合わせると、おおよそ次の順序が返ります(左ほど優先)。

terminal
$ kpsewhich -var-value=TEXMF
{$TEXMFCONFIG,$TEXMFVAR,$TEXMFHOME,!!$TEXMFLOCAL,!!$TEXMFSYSCONFIG,!!$TEXMFSYSVAR,!!$TEXMFDIST}

読み方はこうです。まず自分の設定(TEXMFCONFIG)と作業用(TEXMFVAR)、次に **個人ツリー TEXMFHOME**、その後にサイト全体の TEXMFLOCAL、最後にシステムの設定・作業用・そして配布物 TEXMFDIST。この順番のおかげで、**TEXMFHOME に自分版の mystyle.sty を置けば、配布物より先に見つかって優先されます**。同名でも上書き合戦にならず、個人 → サイト → 配布物という自然な序列で解決されるわけです。(頭に付く !! の意味は次の節で説明します。)

kpathsea — ファイルを探し出す仕組み

ツリーの置き方が決まっても、実際にファイルを探すのは誰か。それが kpathsea(kpse, *kpath search*)という、TeX とその周辺ツールが共有する パス探索ライブラリ です。texpdflatexdvipdfmx などはみな、自前で探さず kpathsea に「amsmath.sty はどこ?」と尋ねます。

kpathsea は探索パスを 文字列の規則 で表します。覚えるべき記号は三つ。$VAR は変数の展開、末尾の **// は「その下を再帰的にすべて探す」 という意味、そして先頭の !! は「ディスクを直接走査せず、後述のファイル名データベースだけを見る」** という指示です。たとえば LaTeX のソースを探すパス TEXINPUTS は、実際にはこんな形をしています。

terminal
$ kpsewhich -var-value=TEXINPUTS
.:$TEXMF/tex/{latex,generic,}//

先頭の .(カレントディレクトリ)を最優先で見て、見つからなければ各 texmf ツリーの tex/ 以下を latexgeneric → その他の順に再帰探索する、と読めます。これで「自分の原稿と同じフォルダのファイルが最優先、なければ配布物から」という直感どおりの挙動になります。

ただし、毎回数万のディレクトリを実際に走査していては遅すぎます。そこで kpathsea は各ツリーの **根に置かれた ls-R というファイル名データベース** を使います。これは「どのファイルがどのディレクトリにあるか」を一覧にしたテキストで、ディスクを舐める代わりにこの索引を引くことで探索が一瞬で済みます。先ほどの !! は「索引だけを信じる(実ディスクは見ない)」指示で、配布物のように滅多に変わらないツリーに付きます。

裏返せば、**ツリーにファイルを足しても、ls-R を作り直すまで TeX はそれを見つけられない** ことがあります(とくに !! の付いたシステムツリー)。索引を再生成するコマンドが **mktexlsr、その別名が texhash** です。TEXMFHOME のような個人ツリーは扱いが緩く再生成不要なことも多いですが、TEXMFLOCAL に何か入れたら次の一行を実行するのが安全策です。

terminal
# Rebuild the ls-R filename databases after adding files to a tree
$ mktexlsr        # texhash is an exact alias

困ったときの最初の一手は、kpsewhich でファイルや変数を直接問い合わせることです。「このファイルはどこから読まれている?」「この変数は何に展開される?」が即座に分かり、設定の食い違いを切り分けられます。kpsewhich の全オプションや、tlmgr などの管理コマンドは別ページで詳しく扱います。

PATH — コマンドへの道

kpathsea が探すのは TeX が 読み込むファイル ですが、その前に、シェルが pdflatex という 実行ファイルそのもの を見つけられなければなりません。これは OS の役目で、環境変数 **PATH** に登録されたディレクトリを順に探します。TeX Live の実行ファイルは OS・アーキテクチャごとの一つの bin ディレクトリにまとまっており、そこを PATH に通すことがインストールの仕上げです。

ディレクトリ名には年号とプラットフォーム名が入ります。Linux なら /usr/local/texlive/2026/bin/x86_64-linux、macOS なら /usr/local/texlive/2026/bin/universal-darwin、Windows なら ...\bin\windows といった具合。macOS では、MacTeX が /Library/TeX/texbin という 年号に依存しない安定したシンボリックリンク を用意してくれるので、毎年更新してもパスを書き換えずに済みます。今どの実体を指しているかは次のように確認できます。

terminal
$ which pdflatex
/Library/TeX/texbin/pdflatex
$ readlink /Library/TeX/texbin
Distributions/Programs/texbin

pdflatex: command not found」と言われたら、十中八九この bin ディレクトリが PATH に無いだけです。OS ごとの具体的な設定手順とインストール後の点検は、インストールのページに譲ります。

texmf.cnf — 設定の総元締め

ここまでの変数(TEXMFTEXINPUTS・各ツリーの場所)は、どこで決まっているのか。その答えが **texmf.cnf という設定ファイルです。kpathsea はあらゆる動作の前にこれを読み、探索パス・各ツリーの位置・メモリ上限などの 動作パラメータ** を取り込みます。本体は配布物の web2c/ 以下にあります。

terminal
$ kpsewhich texmf.cnf
/usr/local/texlive/2026/texmf.cnf

面白いのは、texmf.cnf一つとは限らない ことです。kpathsea は専用の探索パス(変数 TEXMFCNF)に並ぶ複数の場所から texmf.cnf を順に読み、ある変数について最初に見つかった定義を採用 します(後から読むファイルは上書きしません)。つまり、配布物の大きな既定ファイルには手を触れず、優先される場所に小さな上書き用ファイルを置けば、自分の変更だけを安全に追加できる、という重ね合わせの仕組みです。-all を付けると、実際に積み重なっているファイルが見えます。

terminal
$ kpsewhich -all texmf.cnf
/usr/local/texlive/2026/texmf.cnf
/usr/local/texlive/2026/texmf-dist/web2c/texmf.cnf

ここでは上の texmf.cnf(TeX Live が用意する薄い上書き)が、下の texmf-dist/web2c/texmf.cnf(数百行の既定値)より先に読まれます。自分で恒久的に値を変えたいときは、配布物のファイルを直接書き換えるのではなく、TEXMFLOCAL/web2c/texmf.cnf のような より優先される場所 に必要な行だけを書くのが作法です。こうしておけば、ディストリビューションを更新しても設定が失われません。

まとめると、TeX がファイルを見つける流れはこうです。まず texmf.cnf各ツリーの場所と探索パス を定め、その順序に従って kpathsea が(多くは ls-R 索引を引きながら)目的のファイルを探し当て、PATH が実行ファイル自体への入口を与える — この三層が噛み合って、\usepackage{...} の一行が静かに解決されているのです。