なぜ `TMP` と `TEMP` の環境変数が両方あるのか? (2015)
(devblogs.microsoft.com)- Windows には一時ファイルの場所を示す
TMPとTEMPの両方が残っており、両者が異なる場合にどちらが使われるかはプログラムの実装によって異なる - CP/M には環境変数がなかったため、一時ファイルの保存場所はプログラムごとに設定する必要があり、WordStar のようなプログラムでは実行ファイル内の特定のバイトをパッチして動作を変える方式が使われていた
- MS-DOS は CP/M との互換性を強く意識しつつ 環境変数 を追加したが、初期の MS-DOS プログラムは従来の CP/M の慣性により
TEMPやTMPをほとんど使わなかった - MS-DOS プログラムが環境変数を設定保存手段として使い始めると、
TEMPとTMPが競合し、DISKCOPYやEDITのような一部のプログラムはTMPよりTEMPを先に探した - MS-DOS 2.0 のパイプ実装は一時ファイルの場所として
TEMPを選んだが、Windows のGetTempFileNameはTMPを先に確認するため、2 つの変数はそのまま共存し続けることになった
TMP と TEMP が両方残った背景
- Windows の環境変数には、一時ファイルの場所を指定する変数として
TMPとTEMPの両方が存在し、両者が異なる場合にどちらが正しいかはプログラムごとに異なる - 特定のプログラムが一時ファイルをどこに作成するかは、そのプログラムの実装次第であり、Windows プログラムは
GetTempFileName関数を使う可能性が高く、その場合はTMPが優先される - 環境変数設定ダイアログに
TMPとTEMPが並んで表示される理由は、どちらか一方が標準として完全に整理されず、歴史的に異なる選択が共存してきたためである
CP/M には環境変数がなかった
- 1973 年ごろ、マイクロコンピューターで一般的だった OS は CP/M であり、CP/M には環境変数がなかった
- 環境変数がなかったため、
TMPやTEMPの環境変数も存在しなかった - プログラムに一時ファイルの保存場所を指定するには、プログラムごとの設定が必要で、実行ファイル内の特定のバイトをパッチして一時ファイルを置くドライブ文字を指定するような方法が使われていた
- WordStar のようなプログラムは、どのバイトをパッチするとどの動作が変わるかをマニュアルに記載しており、プリンター対応のようなカスタムサブルーチンを組み込めるパッチ用領域も提供していた
MS-DOS と環境変数の登場
- 1981 年に 8086 プロセッサと MS-DOS が登場し、どちらも CP/M の強い影響を受けていた
- MS-DOS の初期設計目標の 1 つは、8080 プロセッサ向けの CP/M プログラムを 8086 プロセッサ向けの MS-DOS プログラムへ機械翻訳できるようにすることだった
- この翻訳器は、自己書き換えコード、命令の途中へのジャンプ、コードをデータとして使う方式のような変則を使わないことを前提としていた
- 8080 の H レジスタと L レジスタは 8086 の BH レジスタと BL レジスタに対応しており、8080 では計算済みアドレスへのアクセスに使えるレジスタが HL だけだったことが、8086 で AX、BX、CX、DX のうちメモリアクセスに BX しか使えなかった理由になっている
- MS-DOS は CP/M 互換性に加えて環境変数も追加したが、既存の CP/M プログラムは環境変数を使っていなかったため、初期の MS-DOS プログラムも環境変数を使用しなかった
- ユーザーが
TEMPやTMPを設定することはできたが、初期のプログラムはそれを気にしていなかった
市場で TEMP と TMP が競合した
- 時間がたち、MS-DOS を主な対象とするプログラムが書かれるようになると、プログラムは環境変数を設定データの保存手段として利用し始めた
- 一時ファイルの場所を指定する環境変数として
TEMPとTMPがそれぞれ使われ始め、両者が主要な候補として浮上した - どの変数を先に確認するかは、プログラム実装上の選択に依存していた
- 多くのプログラムは両方に対応するため
TEMPとTMPの両方を確認したが、どちらを先に見るかは実装ごとに異なっていた - 昔の
DISKCOPYとEDITはTMPよりTEMPを先に探していた
MS-DOS 2.0 のパイプと TEMP
- MS-DOS 2.0 は、あるプログラムの出力を別のプログラムの入力に渡すパイプ機能を導入した
- MS-DOS は単一タスク OS だったため、パイプは最初のプログラムの出力を一時ファイルにリダイレクトして最後まで実行し、その後で 2 番目のプログラムをその一時ファイルを入力として実行する方式で実現されていた
- この機能により、MS-DOS 自体が一時ファイルを作成する場所を必要とするようになった
- その一時ファイルの場所を制御する変数として
TEMPが選ばれた COMMAND.COMがTEMPを選んだとしても、ほかのプログラムがTEMPとTMPのどちらを使うかは依然として各プログラムの判断に委ねられていた
Windows では TMP が優先される経路が生まれた
- Windows でも似たような経緯をたどったが、初期の
GetTempFileName実装はTEMPよりTMPを先に確認するように作られていた - Windows プログラムが一時ファイルを作る際に
GetTempFileNameを使うと、TMPをより優先することになる - したがって、「どの変数が正しいのか」に単一の答えはなく、プログラムがどの API や独自ロジックを使うかによって変わる
- 現在でも環境変数設定ダイアログには
TMPとTEMPの両方が残っており、2 つの変数は一時ファイルの場所をめぐって共存し続けている
1件のコメント
Hacker Newsのコメント
面白いな。自分の時代より前の話なので、CP/Mプログラムをパッチで設定していたなんて聞いたことがなかった
この機能で自分のWordStar向けに、より高速なキーボード・画面出力ルーチンを直接書いたことがある
WordStar 7のドキュメントには、DOSの
debug.exeでプログラムの動作を変えるために使えるパッチ位置が載っていた記憶があるconfig.hを変更して再コンパイルすることで設定するhttps://suckless.org/
付け加えると、このページの別のサブスレッドですでに触れられていたのを後から見つけた
多くのCP/Mプログラムは、32K RAMと低速な130Kフロッピー、ひどい場合はカセットテープ上でも動かなければならなかった。64K RAMと360Kディスクがあればかなり特別な部類だった
当時は今日とは違って、プログラムは市場の上限ではなく下限に合わせて最適化されていた。より多くのシステムで動くほど多く売れたし、顧客にハードウェアのアップグレードを押しつけることもしなかった
外部設定ファイルや、その設定ファイルを作るプログラムを置く余地自体がなく、コマンドライン引数の処理ですら貴重なバイトを消費していた
今ではMacBook NeoのRAMがたった8,000,000,000バイトしかないと不満を言う人もいるが、1978年には 2,048バイトの基本IDE すら作れた
Raymondのブログは好きだが、1973年にマイクロコンピューターでCP/Mが一般的だったというのはおかしい
1973年のマイクロコンピューターは、Intel Intellecのような開発システム級の試作機に近く、OSもなかった。KildallがCP/Mの開発を1973年に始めたのは事実だが、その時点では PDP-10メインフレームのシミュレーター 上でしか動いていなかった
1979年ならまだしも、1973年はさすがに早すぎる
そう考えると、2020年にはChatGPTがなかったのだと思わされる
初期の開発者が深く考えずに下した決定が、何十年も残り続ける ことの好例だ
attorniesという名前のままだろう。初期に誰もスペルミスに気づかなかったからだプログラムが
TMPを選んだのは、MS-DOSのファイル拡張子が最大3文字で、テンポラリファイル名に.TMP拡張子 を使う慣習があったからかもしれないUnixプログラムが
http_proxyを見るのかHTTP_PROXYを見るのか一貫していなかったのと似ている今では多くのプログラムが両方を見るが、確認する順番は同じとは限らない
CP/Mへの言及がやや混乱する。筆者は後で重要になるように振っておきながら、結局 CP/Mや8080 CPUとは関係なかった と説明しているように見える
要点は、Microsoftが自分たちで使っていながら 標準化しようとしなかった ということだけだ
TMPとTEMPのどちらを使うかはすでに標準ができていて、DOSはそれに従ったはずだただ本当の障害は、CP/Mにはディレクトリがなく、DOS 1.0にもなかったという点だ
1995年ごろ、Telstra、つまりAustralia Telecomには組織全体でデスクトップが約5万台あった
ある日、全員のネットワークホームディレクトリに
nullという小さなファイルが現れ、おそらく Unixユーザー が.batファイルを書いてみたのだろうと思った既存の標準になぜ従う必要があるのか、という話だ。「なぜ標準化しなければならないのか」と言いたいところだったが、北米の人たちを混乱させるかもしれないとも思った
/dev/nullを試して失敗し、それでただnullに変えたのだと思うそうでなければUnixプログラマーがやったというのは筋が通らない。むしろDOSプログラマーが
NULをnullと書き間違えた可能性の方が高いハードディスク上の
NULLというファイルを探していて、当然ながら.BATファイルの中に> NULLのような構文があった正直、多くのプログラムでホームディレクトリに ドットファイルをまき散らす方式 より、CP/M式のパッチ設定の方が良かった気もする
Firefoxのように抵抗していたプロジェクトまで含めて、採用するプロジェクトは徐々に増えている
現代のオープンソース的な感覚では似たアプローチと言える。とはいえ、全体的な禁欲主義のせいで好みは分かれそうだ
.configの中にあるべきだ問題は、多くのアプリ開発者が自分のアプリだけは特別で、専用ディレクトリ を持つ資格があると思っていることだ
grepできてテキストエディタで管理できるドットファイルの方がましだと思うもしかすると単に慣れているだけかもしれない
.configフォルダーを強制できるディストリビューションがあるなら、自分にとってはそれが勝者だただ、もうタイミングを逃してしまった気もする
こんなに混乱しているとは思わなかった
教訓はたぶん、常に同じパスを指すようにしろ、さもないと大変なことになる、ということだ
Microsoftのこういういら立たしい点は何十年も指摘してきた
昔は、そこでは何でも知っているかのような「シニア開発者」がいつも答えを持っていたものだ。「
tempは temporary でtmpは troubleshoot my pc、デバッグログ用なんだ。だから俺がシニアでお前は違うんだよ」みたいな調子だった自分がもっとシニアになってみると、疑問を呈したのは正しかったし、今では当時のMicrosoft開発者と話すと ミスだったが下位互換性のために維持した と説明される
だが、その言い訳がなぜ有効なのかと問いたくなる。下位互換性を理由にする一方で、New Outlookのように中核的な互換性や実際の業務フローをしばしば壊す変更は平然と押し通すからだ。そうなると「自分は悪い開発者じゃないから、新しい人たちに聞いてくれ」と逃げる
その新しい人たちにはそもそも聞くことすらできず、彼らはLeetCode式の選考障壁の向こうに隠れている。だからこうした現実の問題が直らず、New Outlookのようなものが出てくるのも不思議ではない。昔のあのシニア開発者が今そこで働いていて、本当の開発者たちはもう引退してしまったのだ
ユーザーのホームのDocumentsフォルダーを勝手なプログラムが不適切に使ったり、OneDriveが誤って強制的に消してしまったりする問題についてMicrosoftからもっともらしい説明を受けても、6か月もしないうちにMicrosoftがランダムな変更を押し込んで挙動を悪い方向に変え、その中核ロジックを台無しにする
Notepadも似たようなものだ。開発者インタビューでは、リスクはゼロであるべきだから非常に単純なプログラムでなければならないと言っていたのに、後になって MicrosoftアカウントのログインとCopilot が付いた
LeetCode式の開発者の姿勢とMicrosoft文化が業界全体を壊していると自分は思う。落ち着いた議論ができず、「お前はMicrosoftで働いていないのだから、その主張は無効だ」という流れになる
Google Chromeが管理者権限を回避するために
AppDataにインストールされていた件は強く印象に残っている。その機能の本来の意図が、第三者が管理者権限なしでインストールするために使えというものではなかったのは明らかだだが当時のChromeは優れていたし、ロックされた企業PC数百万台に第三者の例外プログラムを配布する混乱に対処しなければならなかったので、開発者たちは今ではそれを意図された機能だったかのように言い換えている