大家在使用Windows的时候经常会遇到给文件命名,可以尝试一下 “ CON、PRN、AUX、NUL、COM1~ COM9、LPT1~LPT9 ”这些名称。有同学遇到无法命名时,第一反应觉得是自己电脑中毒了?或者遇到什么问题啦?其实不然~
这个问题需要追溯至1981年的MS-DOS 1.0,当时硬盘上只有一个目录,没有文件夹的概念,设备名 和文件名共用一套名字 。 系统总得有个办法告诉程序“把结果送到屏幕上”等操作吧,于是提前占了一批名字:CON 代表控制台,也就是键盘和屏幕的组合; PRN 指向打印机; AUX 是辅助设备; NUL 则是,你往里面写什么,它都吞掉,不留痕迹 。此外还有 COM1到COM9 (串口)和 LPT1到LPT9 (并口打印机) 。
例如,想把结果直接打印出来,就在文件名那一栏敲上 PRN ;想显示在屏幕上,就敲 CON 。这些名字不是“文件名”,它们是 通往硬件的快捷键 。所以,微软在DOS 1.0里, 预留了一批特殊的“设备名”。
DOS之前,个人电脑上最火的系统叫 CP/M ,你可以把它理解成“DOS 的老前辈”。微软做DOS的时候,一个重要目标就是让用惯 CP/M的人能平滑过渡,所以很多习惯都照搬了。
CP/M 里,设备名是带冒号的,比如 CON: 、 PRN: 。那个冒号就像个标签,明明白白告诉你“这是设备,不是文件”。可DOS觉得冒号太麻烦,大手一挥: 冒号可以不写 。于是 CON 和 CON: 混成了一锅粥,系统再也分不清“一个叫CON的文件”和“我要用控制台”了。
到了1983年,DOS 2.0终于有了文件夹。微软又做了一个顺理成章的决定: 这些设备名,在每个文件夹里都算数 。道理很简单,要是设备名只在根目录管用,你钻进某个子文件夹跑程序,想用 NUL 把输出丢掉就做不到了。为了让老习惯继续可以用,微软选择牺牲掉“在任何地方用CON当文件名”这条路。四十多年后的今天,在文件夹里依然无法命名为 PRN等名称 。
很多人会感觉到奇怪,为什么不改呢?那是因为很多地方都还在用~举一个简单的栗子:在批处理脚本里, >NUL至今 仍是隐藏输出的标准写法。写过代码的小伙伴都明白,如果写了一行代码,不想让他它输出结果,就在这行代码后面加一个 >NUL,这样就相当于代码隐藏运行(无输出)了。这行代码的意思是:删掉Temp目录下的临时文件, 不管成功还是报错,屏幕上不显示任何东西 。
del /q "C:\Temp\*.tmp" >NUL 2>&1
如果有人把这个脚本放到Git Bash里 跑: 它会把 >nul 理解成“ 在当前目录创建一个叫nul的文件,把输出写进去 ”。结果就是:脚本跑完,工作目录下多出一个真实的 nul 文件。世界有无数老脚本、老教程、老习惯,都建立在“NUL是设备、不是文件”这个前提上。 一旦这个前提松动,同一行代码在不同环境里会有区别,排查成本极高。
然鹅,Windows 11并没有 把这条规矩焊死。实测下来, NUL.txt 和 CON.txt 能建成功 ,但并不代表 能正常使用 。根据Superuser上较新的讨论,Windows 11(从22000.3260开始)确实放宽了限制,带扩展名的 CON.txt 、 NUL.txt 可以被创建出来 。但实际使用中,这类文件往往 打不开、删不掉,或者在资源管理器/命令行里行为异常 ,因为底层的Win32 API和设备路径机制仍然会优先把它们识别为设备。微软官方文档至今还写着“NUL.txt 等同于 NUL”,不推荐使用。
从DOS到W indows 11,CON这三个字母像一块被时间封住的琥珀,里头裹着的是设备名和文件名还没分家的年代。
好吧,不用这些名字命名就是了,这样用电脑才能不烧心。
热门跟贴