Windows 文件名实测:保留设备名会静默落空,大小写不敏感会互相覆盖

举报
yd_232353574 发表于 2026/11/01 08:24:05 2026/11/01
【摘要】

起因

处理一批从别的机器上拷过来的目录时,遇到几个诡异的报错:有的文件名明明合法却创建失败,有的文件内容写进去再读出来是空的,还有的目录清单里凭空少了一项。

排查下来是 Windows 的文件名规则在起作用。社区里这块资料不算少,但大多是罗列「CON、PRN、AUX、NUL 是保留名」,没有说清楚实际会发生什么。这篇是我在本机把每一种情况都跑一遍的结果。

保留设备名的实际表现

我在临时目录里逐个尝试创建这些名字,每个都用隔离子进程单独试(有些名字的行为会互相干扰,混在一起测会得出错误结论):

  • CON — 创建「成功」了
  • NUL — 创建「成功」了
  • COM1 — 创建「成功」了
  • con.txt — 创建「成功」了
  • nul.txt — 创建「成功」了
  • PRN — PermissionError: [Errno 13] Permission denied
  • AUX — PermissionError: [Errno 13] Permission denied
  • LPT1 — PermissionError: [Errno 13] Permission denied

看起来是「有些能建有些不能建」,其实不是。这个结果取决于写入的内容去哪了。

CON、NUL、COM1 是 Windows 的设备名。open() 拿这些名字打开的不是一个文件,而是对应的设备:往 NUL 写,数据直接进黑洞;往 CON 写,进控制台。所以「创建成功」这个说法本身是错的,目录里根本没有落下一个文件。

PRN、AUX、LPT1 这几个在当前环境里指向打印机设备,报拒绝访问。

所以真正的规律是:用保留设备名建文件,永远不会得到一个真正的文件。不管 open() 有没有报错。

大小写不敏感,同名文件会互相覆盖

这个特性每个 Windows 用户都知道,但实际影响经常被低估。

我在同一个目录里先写 CaseTest.txt(内容 1),再写 casetest.txt(内容 2),然后列目录:

  • 目录里只有一个文件,名字是 CaseTest.txt(第一次写的那个)
  • 但它的内容是 2

也就是说,两次写入落在了同一个文件上,第二次覆盖了第一次。

这在 Linux 和 macOS 上不会发生,两个名字是两个不同的文件。跨平台同步的时候,一份在 Linux 上生成的 README.md 和一份在 Windows 上生成的 readme.md 会被合成一个。

我查过华为云的存储迁移文档,那里明确写了这条:源端同目录下存在忽略大小写后同名的文件时,目的端只会保留最后一次上传的那个。这不是文档写得保守,是实测就这样。

尾部空格和点会被悄悄吃掉

还有一类情况,Linux 上完全合法,Windows 上会被改写。

我在临时目录里建三个文件,然后列目录看真实结果:

  • 建 trail .txt → 目录里出现 trail .txt(空格保留)
  • 建 trail. → 目录里出现 trail(点被去掉)
  • 建 trail.txt → 目录里出现 trail.txt(尾部空格被去掉)
  • 建 trail_ok.txt → 正常

规律是:文件名中间的空格保留,尾部的空格和尾部的点会被去掉。

这个坑很阴,因为 os.listdir() 返回的名字和你 open() 时用的名字对不上。你写 open('trail.txt ') 能成功,但 os.listdir() 里返回的是 trail.txt,代码里再拼一次路径就找不到文件了。

处理办法很简单:不要让文件名以空格或点结尾。批量处理外部来源的文件名时,先 strip().rstrip('.') 再用。

那次目录清单少了一项是怎么回事

前面提到的「目录清单凭空少一项」,是大小写不敏感 + 尾部空格这两条叠加的结果。

假设来源系统里有三个文件:Data.csv、data.csv、Report.txt 。拷到 Windows 上:

  • Data.csv 和 data.csv 合并成一个
  • Report.txt 变成 Report.txt

三个变两个。而且合并后的内容是后写的那个覆盖前面的。

如果你的程序是「遍历目录然后逐个处理」,那处理数量对不上是必然的。这类问题在跨系统同步场景里特别常见,因为源系统可能是 Linux(区分大小写、允许尾部空格),目标系统是 Windows。

实操做法

  • 保留设备名(CON、PRN、AUX、NUL、COM1~COM9、LPT1~LPT9)连同后缀一起避开。nul.txt 这种带后缀的同样会中招,光看名字带不带后缀判断不了。
  • 跨平台流转前,把文件名统一成小写加短横线,尾部不带空格和点。这一步在源头做,比在目标端补救省事得多。
  • 遍历目录时,不要假设 os.listdir() 的结果和写入时用的路径能对上,用返回的名字重新拼路径再操作。

一句话

Windows 的文件名限制不只是「不能用某些字符」。保留设备名会让写入静默落空,大小写不敏感会让同名文件互相覆盖,尾部空格和点会被静默去掉。跨系统同步前先把文件名规范化,比在目标端逐个排错省力。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。