What’s the deal with those reserved filenames like NUL and CON?

Set the wayback machine to DOS 1.0.

DOS 1.0 didn't support subdirectories, lowercase, or filenames longer than 8.3.

When you ran the assembler (or compiler if you were really fancy) the conversation went something like this:

A>asm foo    the ".asm" extension on "foo" is implied
Assembler version blah blah blah
Source file: FOO.ASM
Listing file [FOO.LST]:
    just hit Enter to accept the default
Object file [FOO.OBJ]:     just hit Enter to accept the default
Assembler cranks away

You only had to type the base name of the file; the ".LST" and ".OBJ" extensions were appended automatically. In fact, I don't think you could disable the extensions; they were always added.

But what if you didn't want a listing file? The assembler demanded a filename, and if you didn't type any filename at all, it created one with the same basename as your source file.

That's where the magic filenames come in. Suppose you wanted the listing file to go straight to the printer. You didn't want to create a file on your floppy drive because there might not be enough space to hold it, or just because you didn't want to waste the time creating a file just to delete it anyway. So you typed "PRN" as the filename.

Now, the assembler doesn't know about these magic filenames. So the assembler will try to create the file "PRN.LST" and then start writing to it. Little does the assembler realize that the output is actually going to the printer.

If you wanted to discard the output entirely, you would type "NUL", of course. And if you wanted it to go to the screen, you would type "CON".

Now, if you followed closely, you can see that the above story explains two things already:

  • Why are the magic filenames magical even if I add an extension?

    Answer: If an extension removed the magic, then when the assembler added ".LST" to the filename, it would no longer be recognized as magical, thereby defeating the purpose of the magic.

  • Why do these magic files exist in every directory?

    Answer: Because DOS 1.0 didn't have subdirectories. There was only one directory, which today we would call the root directory, but back then, since there was no such thing as a subdirectory, there was no need to talk about directories in the first place, much less give the only one you have a name. It was just called "the files on your disk". If magic files didn't work in subdirectories, then when you tried to, for example, chdir into a subdirectory and then run the assembler, you wouldn't be able to type "NUL" as the filename and get the magic.

But why do we carry these magic filenames forward even today?

Because everybody still relies on them. Just look at all the batch files that do things like redirect to >NUL or test if a directory exists by asking "if exist directoryname\nul", or all the documentation that says to create a file with "copy CON ...".

Comments (22)
  1. Anonymous says:

    Jeez I’m old. I knew that one :-(


  2. Anonymous says:

    single sided 160k floppies with no hard drive. Why would anyone want subdirectories. The overhead takes up valuable disk space.

    I can still remember the day we got our original 32k, dual floppy PC from the store. It was the first one they sold. I wish I kept the Technical Reference Manual…

  3. Anonymous says:

    Isn’t it because Unixes have this and CP/M (or what was it), which became MS-DOS, was loosely based on Unix principles? And wasn’t there something with $aux and $clk as well? Or was that OS/2?
    I truly hope that "the next version of Windows" will give the command prompt the same flexibility as Unixes have. The ability to ‘pipe’ data from one commandline app to the next and things like that. The Bash shell is really good at that. I heard rumors that the next command prompt for windows will have support for scripting using the .NET CLR. I hope it will be as good as Bash’s support. Oh, and I know you can get Bash for Windows, but then it’ll try and make your command prompt look like Unix completely, with the forward slashes and all and I don’t like that.

  4. Anonymous says:

    There is an AUX, but I don’t know what clk is.

    MS-Dos was not based on CP/M. CP/M ran on 8080/Z80 processors. The predecessor to MS-DOS was an imitation of CP/M running on the 8088 that some dude in a Seattle computer store had written. I’m sure you can find various versions of the story online. I think it’s also in TV program "Pirates of Silicon Valley", although I imagine if it’s on TV, it can’t be too accurate.

    AUX still works, buy the way, but I have no idea where it goes to.

    Speaking of CON:, there was no good editor initially for the PC, (no Edlin is not a good editor), so people often used Copy CON: filename to type text in a file.

  5. Anonymous says:

    Here’s a link to a site with the history of DOS. It seems I was indeed wrong.

  6. Anonymous says:

    AUX goes, of course, to the AUX device. I think by default, AUX is the same as COM1.

    Back when "dual monitors" meant VGA + monochrome, I wrote a little DOS device driver called OX.SYS that redirected AUX device output to the monochrome display.

    I was going to call it AUX.SYS but that didn’t work! :-)

  7. Anonymous says:

    While you could certainly do the things that Raymond suggests using these "magic filenames," they were indeed part of the CP/M clone heritage of MS-DOS and other operating systems before it that also treat devices as files. The ones I remember: PRN, AUX, CON, LPT1, LPT2, COM1, COM2, NUL, CLOCK$.
    More LPT and COM options were added later, as were some other DOS-specific ones for HIMEM, the MS Mouse, etc.

  8. Anonymous says:

    Yeep – check out 4DOS/4NT at http://www.jpsoft.com. I can’t live without it. I haven’t used *nix in ages, so I don’t know how Unix-y or un-Unix-y it is, but I recommend it either way.

  9. Anonymous says:

    Mike, thanks. I did remember 4DOS when I typed my first response, but I figured it wiuld be discontinued by now. I used it for a while in ’93 or ’94 (also tried NDOS by Norton Enterprises I believe the company was called then).

  10. Anonymous says:

    Wow, I’ve spent a great portion of my life typing copy con and having no idea what it meant. Thanks.

  11. Anonymous says:

    The device names feature actually caused me quite a bit of trouble on the last product I worked on, where typing "lpt1" as the name of your new project would cause the full-screen UI to lock while waiting for a printer. We couldn’t find a 100% reliable way on all Win32 platforms to detect the devices, so we just hardcoded a list of reserved names.

    Also, if you use NT escape syntax to create a file with a full path including a reserved name (\?c:lpt1), all the file query UIs will return the filename to innocent programs, which will happily turn around and open the printer. I created "lpt1" on a guy’s desktop once and it took Explorer 5 minutes to respond every time it refreshed the desktop!

  12. Anonymous says:

    When discussing dos, cmd, 4dos, bash, etc. I must mention one of my small pet projects. It is currently in the planning stage, but here it is anyway:

    I feel that cygwin is too big while cmd is to primitive. There is a minimalistic replacement of "all" bash commands that one uses day-to-day: busybox. Why not make it portable. It seems to rely on a libbb which is included in the source as a separate directory. The biggest problem is probably that it is too much unix-specific, but, hey – I’ll give it a shot today.

  13. Anonymous says:

    Who said we have to wait for “the next version of Windows” to pipe? We have been able to pipe since DOS, and all versions of DOS and Windows command processors support stdout to stdin piping. 4DOS/4NT and NT CMD (if I’m not mistaken) also added ability to pipe (stdout+stderr) to stdin.

  14. Anonymous says:

    Although there is a minimal amount of redirection and piping available in DOS, it’s nowhere near as powerful or flexible as under unix. Something like "cat foo | sort | uniq | head" is just not possible…

  15. Anonymous says:

    hi!, somehow it seems that you are quite into the "old" stuff, so i just try to ask my question on 16-bit Windows in here.
    We still have an old program here, coded in 16-bit Borland Pascal 7.0, which is quite cool (in old terms) by the way.
    Our program requires quite a lot of memory. When the (modern) task manager of Windows XP shows something like 450 MB used by the ntvdm, that is hosting my app, suddenly my app doesn´t get any more memory and quits unexpectly with either a GPF in krnl386.exe or just a GPF in myapp.exe.
    Do you know anything about the big thing behind this, and what are maximum figures and limitations for the use of memory in 16bit programs.
    (hope you know more than me…)
    thx, alois
    PS: Sorry to post here! Please remove my comment, if something like this is not wanted :-)

  16. Anonymous says:

    Mat said: Something like "cat foo | sort | uniq | head" is just not possible…

    While I’m not sure about DOS (it’s been awhile since I’ve used it), any Win32 system (Win9x, WinNT, XP, etc) can certainly do what you describe. Go to http://unxutils.sourceforge.net/ and download the "GNU utilities for Win32"

    inside the usrlocalwbin directory of the zip file, you’ll find cat, sort, uniq, and head (as well as other utilities) that all work exactly as you describe.

  17. Anonymous says:

    You can pipe as many programs as you want (as long as they fit in the limit for a command line), and cat foo | sort | uniq | head is just a matter of whether you have suitable implementations of cat, sort, uniq and head. cat can be loosely replaced with type, sort comes with the OS (although the one from unxutils is somewhat faster), and there are at least two ports of GNU utilities, including uniq and head. One was referenced by jeff in the previous comment, and the other is at http://gnuwin32.sourceforge.net/ .

  18. Anonymous says:

    You CAN write this under Windows 2000/XP :

    dir /b | sort


    netstat /an | find "LISTENING"


    dir >c:tempfile.txt 2>&1

    You can also do wonders with the FOR /F commands, etc. etc.

    Most people just assume that Microsoft is too dumb to implement such basic things. Hint : just type "help" at the command prompt, and/or consult the inline help accessible through the "Start" menu. You might be surprised of what you read.

    That’s not considering any additional software ; if you mix in the win32 version of the GNU toolset or the AINTX tools (http://www.dwam.net/docs/aintx/), then you can do anything you want. Add a little Python for scripting et voilà !


  19. Anonymous says:

    I remember doing some VBA for Access 2.0 and not being able to think for the life of me why the application would crash on my database row that had the value of ‘PRN’.

  20. Anonymous says:

    Pre XP, NUL was also used the verify a CD.

    DC drive: echo F | xcopy /s/e *.* nul

    would copy all of the CD files to a nul dataset.

  21. Anonymous says:

    I have the Technical Reference.

  22. Anonymous says:

    You need to interoperate with batch files

Comments are closed.