Why are there both TMP and TEMP environment variables, and which one is right?


If you snoop around your environment variables, you may notice that there are two variables that propose to specify the location of temporary files. There is one called TMP and another called TEMP. Why two? And if they disagree, then who's right?

Rewind to 1973. The operating system common on microcomputers was CP/M. The CP/M operating system had no environment variables. That sounds like a strange place to start a discussion of environment variables, but it's actually important. Since it had no environment variables, there was consequently neither a TMP nor a TEMP environment variable. If you wanted to configure a program to specify where to put its temporary files, you needed to do some sort of program-specific configuration, like patching a byte in the executable to indicate the drive letter where temporary files should be stored.

(My recollection is that most CP/M programs were configured via patching. At least that's how I configured them. I remember my WordStar manual coming with details about which bytes to patch to do what. There was also a few dozen bytes of patch space set aside for you to write your own subroutines, in case you needed to add custom support for your printer. I did this to add an "Is printer ready to accept another character?" function, which allowed for smoother background printing.)

Move forward to 1981. The 8086 processor and the MS-DOS operating system arrived on the scene. The design of both the 8086 processor and the MS-DOS operating system were strongly inspired by CP/M, so much so that it was the primary design goal that it be possible to take your CP/M program written for the 8080 processor and machine-translate it into an MS-DOS program written for the 8086 processor. Mind you, the translator assumed that you didn't play any sneaky tricks like self-modifying code, jumping into the middle of an instruction, or using code as data, but if you played honest, the translator would convert your program.

(The goal of allowing machine-translation of code written for the 8080 processor into code written for the 8086 processor helps to explain some of the quirks of the 8086 instruction set. For example, the H and L registers on the 8080 map to the BH and BL registers on the 8086, and on the 8080, the only register that you could use to access a computed address was HL. This is why of the four basic registers AX, BX, CX, and DX on the 8086, the only one that you can use to access memory is BX.)

One of the things that MS-DOS added beyond compatibility with CP/M was environment variables. Since no existing CP/M programs used environment variables, none of the first batch of programs for MS-DOS used them either, since the first programs for MS-DOS were all ported from CP/M. Sure, you could set a TEMP or TMP environment variable, but nobody would pay attention to it.

Over time, programs were written with MS-DOS as their primary target, and they started to realize that they could use environment variables as a way to store configuration data. In the ensuing chaos of the marketplace, two environment variables emerged as the front-runners for specifying where temporary files should go: TEMP and TMP.

MS-DOS 2.0 introduced the ability to pipe the output of one program as the input of another. Since MS-DOS was a single-tasking operating system, this was simulated by redirecting the first program's output to a temporary file and running it to completion, then running the second program with its input redirected from that temporary file. Now all of a sudden, MS-DOS needed a location to create temporary files! For whatever reason, the authors of MS-DOS chose to use the TEMP variable to control where these temporary files were created.

Mind you, the fact that COMMAND.COM chose to go with TEMP didn't affect the fact that other programs could use either TEMP or TMP, depending on the mood of their original author. Many programs tried to appease both sides of the conflict by checking for both, and it was up to the mood of the original author which one it checked first. For example, the old DISKCOPY and EDIT programs would look for TEMP before looking for TMP.

Windows went through a similar exercise, but for whatever reason, the original authors of the Get­Temp­File­Name function chose to look for TMP before looking for TEMP.

The result of all this is that the directory used for temporary files by any particular program is at the discretion of that program, Windows programs are likely to use the Get­Temp­File­Name function to create their temporary files, in which case they will prefer to use TMP.

When you go to the Environment Variables configuration dialog, you'll still see both variables there, TMP and TEMP, still duking it out for your attention. It's like Adidas versus Puma, geek version.

Comments (49)
  1. Boris says:

    [That sounds like a strange place to start a discussion of environment variables, but it's actually important.]

    In terms of editing, I don't _quite_ see how CP/M is relevant to the discussion except to clarify that no, it's not because CP/M came up with one and MS-DOS with the other. I was half expecting a weird relationship between patching and the later TMP or TEMP, something like MS-DOS being familiar with common patching locations and exporting their contents to TMP, whereas the new temporary variables would be maintained in TEMP, and then the distinction would be lost as the original CP/M programs gradually disappeared. :)

    [MS-DOS didn't have a standard because CP/M didn't have a standard, so everybody made up their own thing. -Raymond]
  2. mikesart says:

    Great post. Really enjoyed reading how it was done before folks started using env vars. Thanks much.

  3. Gabe says:

    The good news is that most programs ran the first time after being machine translated from CP/M-80. The bad news is that nobody cared.

  4. Clarence says:

    Great article, I have been wondering about the existance of TEMP and TMP a long time. These days, TEMP seems to appear much more often than TMP and I too prefer TEMP (for no particular reason) when referring to the temporary folder in a path.

  5. John Styles says:

    So the, well a, question is is anyone in the world still running a machine translated CP/M-80 program for real (i.e. non nostalgic / 'because it's there') reasons?

  6. Mr Cranky says:

    I actually work on IBM z/OS;  its history goes back to the 1960s, and believe me, there are plenty of leftover artifacts from the days when 64K machines were top-of-the-line.  Not to mention design decisions based on backward compatibility with technology invented as far back as the 1880s.

    Reminds me of that urban legend about how our present railroad track gauge was determined by the Roman Army (http://www.snopes.com/.../gauge.asp).

  7. Kirby FC says:

    [#Boris "In terms of editing, I don't _quite_ see how CP/M is relevant to the discussion"]

    I guess it really isn't.  But, I started with computers in the days of MS-DOS 3.0 so it's always interesting to read about what came earlier.  And, it would have been pretty boring if the entire article consisted of a single sentence: "MS-DOS didn't have a standard because CP/M didn't have a standard, so everybody made up their own thing."

  8. AsmGuru62 says:

    "The design of  both the 8086 processor and  the MS-DOS operating system..."

    Fascinating!

    Does it mean there was collaboration between Microsoft and Intel?

    My apologies for going off topic, but these history bits are so interesting.

    [I oversimplified. There were two steps. Intel wanted 8080 code to be ported easily to CP/M-86. Microsoft wanted CP/M-86 code to be ported easily to MS-DOS. -Raymond]
  9. GhostlyGhost says:

    Is there an accepted or popular way to pronounce "TMP" in speech (to distinguish it from "TEMP") in discussion where both are involved?

  10. Bil Simser says:

    It's a nice piece of history but I guess it just boils down to two different people (at least) coming up with two different ways to address something. Your comment "MS-DOS didn't have a standard because CP/M didn't have a standard, so everybody made up their own thing" really has nothing to do with CP/M (thus I feel the entire post and rabbit hole you took us down was a bit of a waste). There was no standard because nobody thought they should follow them, regardless of where or how the system grew from. In any case, good story but it really just boils down to a couple of guys (or girls) making decisions in a silo.

  11. Karlis says:

    The post was not a waste. It gives us historic context instead of just the final result. I would never have known that MS-DOS added environment variables. And if I had read "MS-DOS added environment variables", I would certainly have wondered "How did they do it before this?".

  12. Yukkuri says:

    would everyone complaining about getting too much information on this post please close the browser tab and just not return? You will ruin it for the rest of us.

  13. Erkin Alp Güney says:

    "The goal of allowing machine-translation of code written for the 8080 processor into code written for the 8086 processor helps to explain some of the quirks of the 8086 instruction set. For example, the H and L registers on the 8080 map to the BH and BL registers on the 8086, and on the 8080, the only register that you could use to access a computed address was HL. This is why of the four basic registers AX, BX, CX, and DX on the 8086, the only one that you can use to access memory is BX."

    Also SI and DI. IX of Zilog 80 maps to SI, IY of Zilog 80 maps to DI. H'L' maps to BP.

  14. Bunk says:

    Gabe: "The good news is that most programs ran the first time after being machine translated from CP/M-80. The bad news is that nobody cared."

    Some people cared. Wordstar was one of those programs (or very nearly so: stackoverflow.com/.../what-was-the-single-byte-change-to-port-wordstar-from-cp-m-to-dos), and it helped to push MS-DOS into viability. Well, Lotus 123 helped a bit...

  15. boogaloo says:

    The single byte change to port wordstar from cpm to dos seems to be a hoax.

    Interestingly on http://www.wordstar.org/.../wordstar-history they say wordstar was ported to CP/M-86 in September 1981. This was a month after the PC came out, but the first version of CP/M-86 didn't get released until April 1982. WordStar CP/M-86 was hacked to run on DOS as a proof of concept in April 1982 and then ported again later.

    It should be possible to prove or disprove by tracking down the original software and nobody seems to have done this, or if they have then they aren't being vocal about it.

  16. Joshua says:

    Maybe it was one byte after mechanical conversion from 8080 to 8086.

  17. boogaloo says:

    CP/M-86 for the IBM DisplayWriter was at least advertised before the IBM-PC version was released.... books.google.co.uk/books

    But wordstar was ported to in 1981, so it probably wasn't that hardware either. That magazine is pretty awesome, take a look at the photos in "A PC Exclusive Interview with Software Guru Bill Gates".

  18. Brad says:

    GhostlyGhost: "Is there an accepted or popular way to pronounce "TMP" in speech (to distinguish it from "TEMP") in discussion where both are involved?"

    To my ear it would be pronounced more like the first syllable of "timpani," while de-emphasizing the "i" sound as much as possible.

  19. Roman says:

    > My recollection is that most CP/M programs were configured via patching. At least that's how I configured them. I remember my WordStar manual coming with details about which bytes to patch to do what.

    Wow. And they say Linux is user-unfriendly. ;-)

    @GhostlyGhost: just say "TEMP" without the E!

  20. Roger says:

    Slightly related, was there any plan for how to deal with updating function names in APIs?  There are several approaches such as - add 'Ex' suffix, add a number (2, 3, 4 etc), add a suffix that indicates the new parameters/functionality (eg Unix/Linux file calls adding 'at' for a directory via a handle), add a #define that selects new versus old names (eg LFS redirecting open to open64) and the list goes on.  They all seem ugly, and Microsoft seems to have overwhelming chosen 'Ex' which falls down the second or third time you update the API.

  21. boogaloo says:

    I have always spelt TMP and said TEMP but that is not fool proof as you're likely to only be talking about it to people who have no clue & they will assume you are talking about TMP when you say TEMP (people who have a clue don't need help setting TMP or TEMP).

    You probably should just always spell it.

  22. morlamweb says:

    Wow.  The very same day that this article was posted, I received advance copies of the documentation for the next release of my application, and in the part where they talk about temp space, the docs now say "Windows Temp and Tmp space requirements".  Previously the doc writers were content with "TEMP space requirements".  What an odd coincidence that I see these new docs on the same day as this article...

    @GhostlyGhost: I usually don't distinguish TMP and TEMP in conversation.  I pronounce them the same: "temp".  Whenever these variables come up in conversation I'm usually on the phone with a customer and a web conference troubleshooting a problem, and we can see both variables on screen, so there's no ambiguity.  On the occasions when I need to distinguish them verbally, I just spell out TMP.

  23. Myria says:

    The 8080/Z80 to 8086 source translation compatibility is also why the registers go in a weird order on x86.  Rather than AX BX CX DX as you'd expect by their names, it's AX CX DX BX.  The reason is that the Z80 register A maps to AX; B and C, often used together as counters, map to CX; D and E map to DX; and as mentioned by Raymond, H and L map to BX.

  24. David says:

    I don't recall the MS-DOS(PC-DOS) 1.0 supported environment variables. I thought those came in with MS-DOS 2.0 and with directory support. This web page seems to bear me out:

    http://www.os2museum.com/.../dos-1-0-and-1-1

  25. laonianren says:

    @GhostlyGhost In my head I've always pronounced "TMP" and "TEMP" as "təmp" and "temp" respectively.  I'm not sure I've ever actually spoken either of them.

  26. Kirby FC says:

    And if you point TEMP and TMP to a location other than the default, and that location becomes no longer available, weird things happen.

  27. boogaloo says:

    @David Your memory is almost certainly correct as the IBM PC DOS 1.0 manual archive.org/.../6172220_DOS_1.0_Jan82 doesn't include the SET command either.

  28. ForOldHack says:

    There are more than 2 temporary variables. the System also has its version of Temp and Tmp also. You can see all these in the system properties, and point them to different temp directories, and look and see which program uses which directory. I put them on a different drive (T:) and use the smallest block size, and it saves a bunch of disk space on the main 4k cluster drive. Internet Explorer also has its cache files, and firefox and chrome have theirs, so now, we are up to 7... Most burning software can use a custom directory for the images... and Outlook?

  29. Yuhong Bao says:

    [I oversimplified. There were two steps. Intel wanted 8080 code to be ported easily to CP/M-86. Microsoft wanted CP/M-86 code to be ported easily to MS-DOS. -Raymond]

    Actually, it was CP/M-80 code being ported directly to 86-DOS/MS-DOS, which is where eg CALL 5 came from.

  30. boogaloo says:

    @Yuhong Bao: It seems a little ironic that MSDOS was more compatible with CPM-80 than CPM-86 was.

    maben.homeip.net/.../CPM%2086%20System%20Guide.pdf

    "Entry to the BDOS is accomplished through the 8086 software

    interrupt #224, which is reserved by Intel Corporation for use by

    CP/M-86 and MP/M-86."

    Hello is that Intel Corporation? We're sorry but we've cancelled your reservation.

  31. Danny says:

    First thing I do after installing Windows is to: 1 - Create a C:TEMP folder and give full right for everyone in there; 2 - Edit TEMP and TMP variable to point to that folder

  32. Anonymous Cow Herd says:

    @Danny

    why?

  33. Malcolm says:

    @Anonymous Cow Herd: I can think of no other reason than convenience. From a security standpoint it's a bit dodgy :)

  34. Malcolm says:

    @Danny: At least if you do that limit it to Administrators Full and Authenticated Users Change ... Everyone is ... well, everyone. Including the unauthenticated.

  35. cheong00 says:

    Btw, the more famous CP/M and DOS relationship is that the "design" of COM/BIN executable format has to be compatible with CP/M, hence the "ORG 100h" in the source files.

    In fact, I've seen lots of COM source files have remarks containing reference to CP/M to that line, suspected to be remains of the original source template.

  36. cheong00 says:

    @Malcolm: That's why we have the local policy rule that exclude anomymous user from "Everyone".

  37. Blade says:

    Wrong.

    TMP started with Unix (or perhaps earlier), and TEMP started with MS-DOS (possibly even later than 2.0, as I don't think getTempFileName or whatever it was called landed in the OS until 3.x, so there may not have even been a standard for DOS before then, in which case it was entirely up to the program authors which one to use... Developers used to Unix probably used TMP, while Borland and others that weren't Unix devs used TEMP... or DOS 3.x gave that to them.  (correct me if i'm wrong that Microsoft introduced TEMP officially in 2.0)

  38. grumpy says:

    re Blade

    I wonder what's up with people who feel the need to write assertive comments about stuff they don't know a thing about, even though it's obvious from their words that they have no clue?

    In this case, "getTempFileName or whatever it was called" wasn't called anything at all. MS-DOS didn't have function-based API. Which kinda reveals the true depth of knowledge of the previous comment author.

  39. cheong00 says:

    @grumpy: While it's true that in the age of DOS we only have function redirects in forms of interrupts, but these interrupts did indeed have names assigned to them, and so does each sub-function assigned by DOS ( en.wikipedia.org/.../MS-DOS_API ) , so I don't have question for the line.

    Btw, just in case you don't know, for DOS function calls, it was spoken in this way: "INT 21h, function 4Ch"

  40. Somebody says:

    @grumpy: Blade is right. I also knew Unix first, and therefore the variable TMP. At this time, DOS (respective some DOS programs) used TEMP. And as far as I remember, also Windows 95 only used TEMP.

    When Windows NT arrived and had both defined, I though it was because of the POSIX subsystem of NT 3.51 and because some UNIX utilities are ported to Windows NT (like lpr.exe, sh.exe and such).

  41. dirk gently says:

    >Is there an accepted or popular way to pronounce "TMP" in speech (to distinguish it from "TEMP") in discussion where both are involved?

    I'd say "tea em pee" vs. "temp"

  42. grumpy says:

    @cheong00

    Those are not names, those are descriptions (as you might read on the Wikipedia page you refer to). Those are not normative, you'll get different wording depending on the reference literature you read. Just in case you don't know, for DOS function calls, it was spoken in this way: "INT 21h, function 4Ch". (Yes, it's my line, not yours. It follows from what I said, and it contradicts what you said). As an MS-DOS programmer, it would never came into my mind to invent a fictitious function name for a DOS or BIOS function, we thought of them as "function xx of interrupt yy" at the time. That's one reason why Blade's comment stroke me as ignorant.

    Another reason is that there is no function for getting a temp path in DOS API, contrary to what he writes.

    @Somebody

    Please re-read Blade's comment and say again in what way he is right.

    He gets all his facts mixed up, probably confuses DOS with Windows, and based on that categorically asserts that the article is "WRONG".

    Whether some of the application developers were inspired by their UNIX habits or not is beside the point.

  43. John Elliott says:

    CP/M finally did get the notion of a temporary path (well, temporary drive, it not having paths) in 1982. CALL 5 with C=31h (S_SYSVAR), DE pointing at a word containing 50h (read system variable 80)

  44. Danny says:

    @Malcom. Yes, primarily convenience. Also if the anonymous is already logged into my PC, having full rights into C:TEMP is the least of my worries. To quote Ray's favorite phrase "he is already on the other side of the hatch".

  45. dirk gently says:

    > the H and L registers on the 8080 map to the BH and BL registers on the 8086, and on the 8080, the only register that you could use to access a computed address was HL. This is why of the four basic registers AX, BX, CX, and DX on the 8086, the only one that you can use to access memory is BX

    Well, it doesn't really explain why it's the *only* register. I mean, it could have as well allow more registers to be used to do stuff, as long as it's not *less* registers than in 8080 it's all good, right?

  46. Just One More Byte says:

     "For whatever reason, the authors of MS-DOS chose to use the TEMP variable to control where these temporary files were created"

    Given the pressing need to reduce memory usage using whatever means available, adding 1 extra byte must be the first instance of bloatware at Microsoft.

  47. Mark says:

    Danny: what you're saying is that various virtual machines (e.g. Java) should be subvertable on your machine because you like having a special temp directory. What convenience does C:TEMP add over %TEMP%?

  48. Danny says:

    @Mark. The various virtual machines, Java included seems to like my setup. Furthermore environment variable %TEMP% does refers to my C:TEMP. Furthermore I don't like to go into C:Users<name>Local SettingsTemp folder in order to look for some temp file that gets created, when I want to have a closer look. Plus I like to manage deletion of temp folder myself instead of running the Windows wizard. So you see, I have a good reason to make it so short and easy accessible from human point of view.

  49. pyro says:

    @Danny as you yourself told - %TEMP% points to your C:Temp, so what is the difference, beyond potential cross contamination by other users and less secure access rights?

Comments are closed.

Skip to main content