Windows和Linux目录名中禁止使用哪些字符?

Jef*_*eff 315 linux windows directory zip filenames

我知道/在Linux中是非法的,以下在Windows中是非法的(我认为) * . " / \ [ ] : ; | , *

我还缺少什么?

但是,我需要一个全面的指南,并且需要考虑双字节字符.链接到外部资源对我来说没问题.

我需要首先使用可能包含禁用字符的名称在文件系统上创建一个目录,所以我打算用下划线替换这些字符.然后我需要将此目录及其内容写入zip文件(使用Java),因此有关zip目录名称的任何其他建议将不胜感激.

Chr*_*bek 439

让我们保持简单并首先回答问题.

  1. 禁止打印的ASCII字符是:

  2. 不可打印的字符

    如果您的数据来自允许不可打印字符的来源,则需要检查更多内容.

    注意:虽然在Linux/Unix文件系统下创建文件名中包含控制字符的文件是合法的,但用户处理此类文件可能是一场噩梦.

  3. 保留的文件名

    以下文件名是保留的:

    • 视窗:

      CON, PRN, AUX, NUL 
      COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9
      LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9
      
      Run Code Online (Sandbox Code Playgroud)

      (例如,他们自己和任意文件扩展名LPT1.txt).

  4. 其他规则

    • 视窗:

      文件名不能以空格或点结尾.

  • 其他人已经说过,这不是建设性的.当我来到这里寻找答案时,我想要我必须在其他地方收集的列表:在创建有效文件名的良好尝试时,从用户输入过滤掉哪些字符.如果角色一起变得无效的问题,也可能需要一些细化. (32认同)
  • @Soaku:当然不是,因为世界并非围绕着微软.为什么只有两个字符是绝对必要的禁止时添加不必要的限制? (10认同)
  • `*?<>"` 字符被保留为[通配符](https://blogs.msdn.microsoft.com/jeremykuhne/2017/06/04/wildcards-in-windows)。这是由于一种特殊的设计决策是让文件系统在“NtQueryDirectoryFile”系统调用的实现中在低级别实现过滤目录列表。在 POSIX 系统中,这是在应用程序级别实现的。 (7认同)
  • 请注意,在将 DOS 路径转换为本机 NT 路径时,运行时库将应用保留的 DOS 设备名称以及有关以点或空格结尾的文件名的规则。如果路径以“\\?\”本地设备前缀开头,则将跳过此规范化步骤,除非将“\\?\”替换为 NT 的“\??\”设备前缀。此前缀指示对象管理器在登录会话和全局 DOS 设备目录中搜索到本机 NT 设备的符号链接,该设备通常是“\Device”目录中的设备对象。 (6认同)
  • Linux上也禁止使用NULL字符. (5认同)
  • 大多数Windows文件系统不限于8位字符.Windows上禁止使用许多其他8位字符(NUL,控制字符).即使考虑到那些也不允许提问者"在文件系统上创建一个目录",因为他提出了无限数目的无效目录名称. (4认同)
  • OTOH,保留字符不仅仅是 DOS 命名空间的功能。它们保留在内核和文件系统的较低级别。“\”字符是 NT 的路径分隔符,由对象管理器保留。对象名称中允许使用其他任何内容,其中包括 DOS 设备名称,例如“C:”​​。其他保留字符(包括 ASCII 控制字符)是由内核的文件系统运行时库引起的,该库由 Microsoft 文件系统使用。这些字符保留在主文件名中,而不是流名称中。 (4认同)
  • 有趣的事实:使用 Cygwin 您可以轻松创建“lpt1”和“lpt1.txt”。**然后尝试在 Windows 资源管理器中删除它们**:您不能。或者在`cmd.exe`中:你不能。不过 Cygwin 可以。这似乎是 20 世纪 80 年代的限制,是人为帮助的。 (4认同)
  • Linux上不禁止换行.我认为它们应该是,但是......如果NUL在Linux上被禁止,那么它在Windows上被禁止,它就会达到同样的目的. (3认同)
  • 从技术上讲,Windows 中的文件名可以以空格结尾,但文件资源管理器无法与其正确交互。它只能与使用 UNC 路径进行交互。亲眼看看,你可以做`echo; > 命令提示符中的“\\?\%CD%\test "`。您会注意到您无法在资源管理器中删除或打开它。使用 `del "\\?\%CD%\test "` 删除它,或使用 `ren "\\?\%CD%\test " "test"` 重命名它。这并不是真正有用的信息,但如果您遇到过带有尾随空格的文件,了解这一点是很方便的。 (3认同)
  • @firegurafiku "/" 只是约定 - 目录名无论如何都是彼此分开存储的,因此 '/' 可以毫无问题地出现在名称中(如果允许)。如果在路径内的目录/文件名中使用,则必须对其进行筛选,但许多其他字符也是如此。处理 '\0' 将涉及到处单独存储字符串长度,这实际上更难。 (2认同)
  • “CONIN$”和“CONOUT$”也被保留。与“CON”不同,它们允许通过读写访问访问控制台输入和屏幕缓冲区。在 Windows 8 之前,仅保留基本文件名。从 Windows 8 开始,底层控制台 IPC 被重新设计为使用设备驱动程序,因此这两个名称现在通常作为 DOS 设备处理,与“NUL”等相同。这意味着它们可以在本地设备路径中使用,例如“\\.\CONIN$”和“\\?\CONOUT$”,并且 API 假装名称“存在”在每个现有目录中。例如,“C:\Temp\CONOUT$”引用控制台输出。 (2认同)
  • “在大多数Linux发行版中,您都可以使用正斜杠来命名文件。” -不,你不能。“ /”始终被内核(而不只是外壳)视为目录分隔符。无法使用C程序或Python脚本或任何其他方式解决此问题。 (2认同)
  • 补充有趣的事实:您可以通过编程方式创建带有“*”和“?”的文件。在 Windows 上的名称中。所以从技术上来说,并不违法;只是一个非常非常糟糕的主意。(顺便说一下,删除名为“lpt1”的文件的解决方案是“ren lpt? lptx”。删除名为 *.\* 的文件可能更具挑战性)。 (2认同)
  • 在 MacOS 上,唯一禁止的可打印 ASCII 字符是 `:`。使用 Windows 禁止字符超集是明智的,因为它也涵盖了 Linux 和 MacOS。 (2认同)

Dou*_*rch 204

禁用文件名字符的"综合指南"在Windows上不起作用,因为它保留了文件名和字符.是的,* " ?禁止使用像和其他人一样的字符 ,但是有无数个名称仅由禁止使用的有效字符组成.例如,空格和点是有效的文件名字符,但禁止仅由这些字符组成的名称.

Windows不区分大写字符和小写字符,因此A如果a已存在名称,则无法创建命名文件夹.更糟糕的是,看似允许的名称PRNCON,以及许多其他名称都是保留的,不允许使用.Windows也有几个长度限制; 如果移动到另一个文件夹,在一个文件夹中有效的文件名可能会无效 命名文件和文件夹的规则 在MSDN上.

通常,您不能使用用户生成的文本来创建Windows目录名称.如果你想允许用户名字,他们想要的东西,你必须创建安全的名字,如A,AB,A2等,存储用户生成的名称和应用程序数据文件的路径等价物,并在你的应用程序中执行路径映射.

如果绝对必须允许用户生成的文件夹名称,则判断它们是否无效的唯一方法是捕获异常并假设名称无效.即使这样也充满了危险,因为拒绝访问,脱机驱动器和驱动器空间的异常与可能因无效名称而被抛出的异常重叠.你正在开辟一个巨大的伤害.

  • 有一些指导方针,*"有无限数量的名称仅由禁止的有效字符组成"*不具有建设性.同样*"Windows不区分大写和小写字符"*是一个愚蠢的例外 - OP询问语法而不是语义,没有正确的人会说文件名像`A.txt `***因为`a.TXT`可能存在. (57认同)
  • 来自MSDN链接的关键短语是"[和]一个目标文件系统不允许的其他字符".Windows上可能有不同的文件系统.有些可能允许使用Unicode,有些可能不允许.通常,验证名称的唯一安全方法是在目标设备上尝试它. (9认同)
  • @JimBalter除非我误解了,否则它不是建设性的,因为如果文件名的规则定义明确并且本身不是无限的,那么“仅由禁止的有效字符组成的无限数量的名称”是毫无意义的。这个答案中没有任何理由以对读者有帮助或有用的方式将可能性描述为无限。例如对比如下: (1) 在Linux 中,不允许使用“/”。(2) Linux 不可能有全面的指南,因为有无数个不允许的名称,例如“/”、“//”、“///”、“a/a”、“b/b”等。 (9认同)
  • `COPY CON PRN`表示从键盘输入或可能的标准输入读取,并将其复制到打印机设备.不确定它在现代窗户上是否仍然有效,但肯定是很长一段时间.在过去,您可以使用它来键入文本,并使用点阵式打印机输出它. (8认同)
  • "通常,您不能使用用户生成的文本来创建Windows目录名称." < - 如果你想这样做,你可以拥有一个角色白名单,如果你可以忽略已经存在的问题,它将在很大程度上起作用. (3认同)
  • 请注意,Windows 文件名不区分大小写的假设是不正确的。更糟糕的是,Windows 上的区分大小写规则[现在可以按目录设置](https://learn.microsoft.com/en-us/windows/wsl/case-sensitivity)。 (3认同)
  • 您不应该允许用户访问文件结构地址的想法是合理的,但措辞非常糟糕。用户应该能够检查和操作应用程序向他们公开的实体。虽然这些实体可能是多个数据库的动态命名摘要,但向用户询问文件名并没有错。应用程序的安全性应防止用户犯错和越权;他们不应该阻止他们做他们需要做的事情 (2认同)
  • “不是建设性的”-相反,这是事实。没有什么建设性的是鲍罗丁的好战。 (2认同)
  • 老实说,“您通常不能使用用户生成的文本来创建Windows目录名称”这一观点有点荒谬。在很多情况下,您希望允许用户命名其文件和文件夹,因此仅说“不做”是没有帮助的。 (2认同)

Jon*_*ler 62

在Linux和其他与Unix相关的系统中,只有两个字符不能出现在文件或目录的名称中,而且它们是NUL '\0'和斜杠'/'.当然,斜杠可以出现在路径名中,将目录组件分开.

谣言1认为Steven Bourne('shell'成名)有一个包含254个文件的目录,每个单个字母(字符代码)一个可以出现在文件名中(不包括/,'\0';名称.是当前目录,当然).它被用来测试Bourne shell,并经常对诸如备份程序之类的粗心计划造成严重破坏.

其他人已经涵盖了Windows规则.

请注意,MacOS X具有不区分大小写的文件系统.


1 编程实践中的 Kernighan&Pike在第6章测试,§6.5压力测试中说了很多:

当Steve Bourne编写他的Unix shell(后来被称为Bourne shell)时,他创建了一个包含一个字符名称的254个文件的目录,每个字节值除了一个字符值'\0'和斜杠,这两个字符在Unix中不能出现文件名.他使用该目录进行模式匹配和标记化的各种测试.(测试目录当然是由程序创建的.)多年后,该目录是文件树行走程序的祸根; 它测试了它们的破坏.

  • 254个文件都是单字符文件名,文件名中允许的每个字符一个.当史蒂夫伯恩写下Bourne shell时,UTF-8甚至不是眼前一亮.UTF-8对有效的字节序列施加规则(并且完全不允许字节0xC0,0xC1,0xF5-0xFF).否则,它没有太大的不同 - 在我正在讨论的细节层面. (19认同)
  • MacOS HFS+ 文件系统的磁盘目录分隔符实际上是一个“:”而不是“/”。当您使用 *nix API 时,操作系统通常(可能总是)会做正确的事情。但是,如果您要迁移到 OSX 世界,例如使用 applescript,请不要指望这会可靠地发生。看起来 Cocoa API 可能会使用 / 并且对您隐藏 : ,但我很确定旧的 Carbon API 不会。 (2认同)
  • FWIW:在运行 macOS Big Sur 11.7 的 MacBook Pro 上,我可以创建一个名为“:”的文件,但我无法创建一个完整名称为任何单字节 0xC0、0xC1、0xF5..0xFF 的文件,也不能与任何 UTF-8 连续字节 0x80..0xBF。错误编号为 92“非法字节序列”。由此,我推断 macOS 坚持文件名是不包含“/”或空字节的有效 UTF-8 字符串。我还没有检查 U+FFFF 等非字符、代理范围、PUA(专用区域)范围以及未分配代码块中的字符(例如 U+80000..U+8FFFF)。 (2认同)

Aeo*_*ime 32

您可以使用白名单,而不是创建字符黑名单.考虑到所有因素,在文件或目录名称上下文中有意义的字符范围很短,除非您有一些非常具体的命名要求,否则如果用户不能使用整个ASCII表,则用户不会将其保留在应用程序中.

它不能解决目标文件系统中保留名称的问题,但使用白名单可以更轻松地降低源上的风险.

本着这种精神,这是一系列可以被认为是安全的角色:

  • 字母(az AZ)- 如果需要,也可以使用Unicode字符
  • 数字(0-9)
  • 下划线(_)
  • 连字符( - )
  • 空间
  • 点(.)

以及您希望允许的任何其他安全字符.除此之外,您还必须执行一些有关空格和点的其他规则.这通常就足够了:

  • 名称必须至少包含一个字母或数字(以避免只有点/空格)
  • 名称必须以字母或数字开头(以避免引导点/空格)
  • 名称可能不以点或空格结尾(如果存在,只需修剪它们,就像资源管理器那样)

这已经允许非常复杂和荒谬的名称.例如,这些名称可以使用这些名称,并且是Windows/Linux中的有效文件名:

  • A...........ext
  • B -.- .ext

从本质上讲,即使白名单字符很少,您仍然应该确定实际有意义的内容,并相应地验证/调整名称.在我的一个应用程序中,我使用了与上面相同的规则,但剥离了任何重复的点和空格.

  • 那些非英语用户怎么样呢?谁都会被这个搞砸? (10认同)
  • “考虑到所有因素,在文件或目录名称上下文中有意义的字符范围非常短。” 也许对于某些用例。我正在开展一个项目,现在涉及 20 种语言的媒体文件,文件名需要反映媒体项目的标题,因为最终用户将通过这种方式找到内容。许多名称使用标点符号。对文件名字符的任何限制都是有代价的,因此在这种情况下,我们必须尽量减少限制。在这个用例中,*不*在文件名中有意义的字符范围比那些有意义的字符范围要短得多,也更简单。 (5认同)
  • 如今,许多程序的现实是,您不知道客户是谁,或者他们将使用什么语言。例如,如果您要在应用商店、Windows 或 Apple 商店中向公众发布。默认情况下,您可以将您的软件设置为仅限英语(或仅限欧洲),这是一种常见的方法……对于使用其他语言的人来说,搜索软件以满足他们的需求是一种令人沮丧的方法。对于开发商来说,这也可能是一种可以避免的收入损失。将程序设计为很大程度上与脚本无关,并不需要花费太多精力。 (5认同)
  • 我们使用白名单方法,但不要忘记在 Windows 上您必须管理保留的、独立于大小写的字符串,如设备名称(prn、lpt1、con)和 . 和 .. (4认同)
  • 我想说任何好的代码都会说明它的含义。在这种情况下,白名单感觉很像一种“货物崇拜”解决方案,在数百万个“未知的未知数”的情况下会崩溃。你并不是不允许“不可能”的值,而是不允许你不敢测试的值。 (4认同)
  • @pkh:正如我在我的帖子中提到的,您可以在白名单中包含任何需要的 unicode 字符。字符范围通常可以很容易地指定,尤其是当您使用正则表达式时。 (3认同)
  • “您可以在白名单中包含任何需要的 unicode 字符。通常可以很容易地指定字符范围” - 为任意(事先未知)语言执行此操作将是非常重要的。在某些正则表达式引擎中,您可以使用类别,例如 `\p{L}\p{M}*` (https://www.regular-expressions.info/unicode.html) 将任何字母及其变音符号一起列入白名单。但它不会包括非罗马文字中的数字、句点、连字符、下划线等等价物。 (3认同)
  • 您错过了Windows限制:不得以点或空格结尾. (2认同)
  • @LarsH您还可以尝试允许尽可能多地使用unicode,如下所示:/sf/answers/4301406091/ 实际上,几乎所有内容都是允许的,所以白名单可能不是最好的方法。 (2认同)
  • @AeonOfTime 啊,在这种情况下,我建议将该行改写为简单的_“名称不得以点或空格开头”_。 (2认同)

Leo*_*era 28

好吧,如果仅用于研究目的,那么最好的办法是查看文件名上的维基百科条目.

如果你想编写一个可移植的函数来验证用户输入并根据它创建文件名,那么简短的答案就是不这样做.看看像Perl的File :: Spec这样的便携式模块,可以一瞥完成这种"简单"任务所需的所有跳跃.


小智 26

让Windows告诉您答案的简单方法是尝试通过资源管理器重命名文件并输入/为新名称.Windows将弹出一个消息框,告诉您非法字符列表.

A filename cannot contain any of the following characters:
    \ / : * ? " < > | 
Run Code Online (Sandbox Code Playgroud)

https://support.microsoft.com/en-us/kb/177506

  • 我记得以前也是这样的。我刚刚在 Windows 10 中尝试过,该消息框不再显示,而是播放声音。 (3认同)

Cad*_*oiz 9

讨论不同的可能方法

与界定困难,什么是合法的,而不是已经不客气和白名单被提出。但是 Windows支持超过 8 位的字符。维基百科指出,(例如)

修饰符字母冒号[(参见下面的 7.)是] 有时用于 Windows 文件名,因为它与用于文件名的Segoe UI字体中的冒号相同。[继承的 ASCII] 冒号本身是不允许的。

因此,我想提出一种更自由的方法,使用 Unicode 字符替换“非法”字符。我发现我的可比用例中的结果更具可读性。此外,您甚至可以从替换中恢复原始内容。

可能的选择和研究笔记

为了使事情井井有条,我将始终给出字符、名称和十六进制数字表示。这不区分大小写,可以自由添加或省略前导零,因此例如U+002Au+2a是等效的。如果可用,我会尝试指出更多信息或替代方案 - 请随时向我展示更多或更好的信息。

  1. 代替*( U+2A * ASTERISK),您可以使用列出的众多方法之一,例如U+2217 ? (ASTERISK OPERATOR)Full Width Asterisk U+FF0A ?。我还包括了Wally Brockway 的回答的一些好的建议,在这种情况下u+20f0 ? combining diacritical marks for symbols- 从现在开始我将用?.
  2. 而不是.( U+2E . full stop),这些之一可能是一个不错的选择,例如? U+22C5 dot operator
  3. 除了"( U+22 * quotation mark),您还可以使用“ U+201C english leftdoublequotemark, u+2036 ? reversed double prime? 或者u+2033 ? double prime (替代方案见这里
  4. 代替/( U+2F / SOLIDUS),您可以使用? DIVISION SLASH U+2215(others here ) 或u+2044 ? fraction slash?
  5. 代替\( U+5C Reverse solidus),您可以使用? U+29F5 Reverse solidus operator ( more ) 或u+20E5 ? combining reverse solidus overlay?
  6. 要替换[( U+5B [ Left square bracket) 和]( U+005D ] Right square bracket),您可以使用例如U+FF3B? FULLWIDTH LEFT SQUARE BRACKETU+FF3D ?FULLWIDTH RIGHT SQUARE BRACKET(从这里开始,更多可能性在这里
  7. 您可以使用或代替: ( u+3a : colon),(请参阅冒号(字母),有时在 Windows 文件名中使用,因为它与用于文件名的Segoe UI字体中的冒号相同。冒号本身是不允许的......源和更多替换见这里)。另一种选择是这个:U+2236 ? RATIO (for mathematical usage)U+A789 ? MODIFIER LETTER COLONu+1361 ? ethiopic wordspace ?
  8. 代替;( u+3b ; semicolon),您可以使用U+037E ? GREEK QUESTION MARK(请参阅此处) )
  9. 对于|( u+7c | vertical line),有一些很好的替代品,例如:U+2223 ? DIVIDES, U+0964 ? DEVANAGARI DANDA, U+01C0 ? LATIN LETTER DENTAL CLICK维基百科的最后一个)或U+2D4F ? Tifinagh Letter Yan。还有框画人物包含各种其他选项。
  10. 代替,( , U+002C COMMA),您可以使用例如‚ U+201A SINGLE LOW-9 QUOTATION MARK(参见此处
  11. 对于?( U+003F ? QUESTION MARK),这些是很好的候选者:U+FF1F ? FULLWIDTH QUESTION MARK或者U+FE56 ? SMALL QUESTION MARK(从这里这里)还有两个来自Dingbats 块(搜索“问题”)和u+203d ? interrobang?
  12. 虽然我的机器似乎接受它不变,但为了完整起见,我仍然想包括>( u+3e greater-than sign) 和<( u+3c less-than sign) 。这里最好的替换可能也来自引用块,例如 u+203a › single right-pointing angle quotation marku+2039 ‹ single left-pointing angle quotation mark分别。tifinagh 块只包含? (u+2D66)? 替换<. 最后一个概念是? less-than with dot u+22D6? greater-than with dot u+22D7

对于其他想法,您还可以查看此块的示例。

你怎么打这些字符

假设您要键入? (Tifinagh Letter Yan). 要获取其信息,您始终可以在合适的平台上搜索此字符,例如Unicode Lookup(搜索十六进制时添加 0x)或此Unicode 表(仅允许搜索名称,在这种情况下为“Tifinagh Letter”颜”)。您应该获得它的 Unicode 编号U+2D4F和 HTML 代码&#11599;- 请注意,2D4F对于11599. 有了这些知识,您有多种选择来生成这些特殊字符,包括使用

  • 代码指向 unicode 转换器或再次指向Unicode Lookup反向,将数字表示转换为 unicode 字符 - 分别将下面的代码点基数设置为十进制或十六进制
  • Autohotkey 中的单行 makro ::?*:altpipe::{U+2D4F}输入?而不是字符串altpipe- 这是我输入这些特殊字符的方式,如果有共同的兴趣,我的 Autohotkey 脚本可以共享
  • Alt字符或替代代码通过按住alt,然后是所需字符的十进制数(更多信息例如这里,查看这里那里的表格)。例如,那将是Alt+ 11599。请注意,许多程序并不完全支持所有 unicode 的此 Windows 功能(截至撰写本文时)。中号ICRO小号经常办公室是一个例外,它通常工作,其他一些操作系统提供类似的功能。将这些带有 Alt 组合的字符输入 MS Word 也是Wally Brockway他的回答中建议的方式已经提到过 - 如果您不想将所有十六进制值传输到十进制asc.,你能在那里找到其中的一些吗?
  • 在 MS Office 中,您还可以使用ALT+X这篇 MS 文章中所述来生成字符
  • 如果你很少需要它,你当然仍然可以复制粘贴你选择的特殊字符而不是输入它

  • 如果 unicode 联盟的“某人”仅为“滥用非法字符的愚蠢操作系统”保留一个范围,其字体映射将映射到“非法字符字形”但有所不同,那就太好了。甚至替代?有不同的宽度和特性,导致我想要更换!即使如此,当高度与“.”不一致时也会很恼火。(例如)。 (2认同)

Bre*_*ron 7

在 Windows 10 (2019) 中,尝试输入以下字符时会出现错误,禁止使用这些字符:

文件名不能包含以下任何字符:

\ / : * ? " < > | 在此输入图像描述

  • 可能重复 /sf/answers/2279599031/ (3认同)

Kar*_*eji 6

对于任何寻找正则表达式的人:

const BLACKLIST = /[<>:"\/\\|?*]/g;
Run Code Online (Sandbox Code Playgroud)


小智 5

对于Windows,您可以使用PowerShell进行检查

$PathInvalidChars = [System.IO.Path]::GetInvalidPathChars() #36 chars
Run Code Online (Sandbox Code Playgroud)

要显示UTF-8代码,您可以转换

$enc = [system.Text.Encoding]::UTF8
$PathInvalidChars | foreach { $enc.GetBytes($_) }

$FileNameInvalidChars = [System.IO.Path]::GetInvalidFileNameChars() #41 chars

$FileOnlyInvalidChars = @(':', '*', '?', '\', '/') #5 chars - as a difference
Run Code Online (Sandbox Code Playgroud)

  • 对于不会使用 PowershelI 的用户,$FileNameInvalidChars 为 0x00 到 0x1F,并且:" &lt; &gt; | * ? \ / (2认同)