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

我还遗漏了什么?

然而,我需要一份全面的指南,一份考虑到各种因素的指南 双字节字符。链接到外部资源对我来说很好。

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


当前回答

在Linux和其他与unix相关的系统下,传统上只有两个字符不能出现在文件或目录的名称中,那就是NUL '\0'和斜杠'/'。当然,斜杠可以出现在路径名中,分隔目录组件。

有传言说,史蒂文·伯恩(因“贝壳”而出名)有一个包含254个文件的目录,一个文件对应一个可以出现在文件名中的每个字母(字符代码)(不包括/,'\0';名字。当然是当前的目录)。它被用来测试伯恩外壳,并经常对备份程序等不小心的程序造成严重破坏。

其他人已经介绍了Windows文件名的规则,并提供了微软和维基百科的相关链接。

注意MacOS X有一个不区分大小写的文件系统。目前的版本似乎允许在文件名中使用冒号,尽管在历史上并不一定总是这样:

$ echo a:b > a:b
$ ls -l a:b
-rw-r--r--  1 jonathanleffler  staff  4 Nov 12 07:38 a:b
$

但是,至少在macOS Big Sur 11.7中,文件系统不允许文件名不是有效的UTF-8字符串。这意味着文件名不能由UTF-8中始终无效的字节组成(0xC0, 0xC1, 0xF5-0xFF),并且不能使用延续字节0x80..0xBF作为文件名中的唯一字节。给出的错误是92非法字节序列。

POSIX定义了一个可移植文件名字符集,包括:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 . _ -

坚持使用完全由这些字符组成的名称可以避免大部分问题,不过Windows仍然增加了一些复杂性。


1

It was Kernighan & Pike in ['The Practice of Programming'](http://www.cs.princeton.edu/~bwk/tpop.webpage/) who said as much in Chapter 6, Testing, §6.5 Stress Tests:

When Steve Bourne was writing his Unix shell (which came to be known as the Bourne shell), he made a directory of 254 files with one-character names, one for each byte value except '\0' and slash, the two characters that cannot appear in Unix file names. He used that directory for all manner of tests of pattern-matching and tokenization. (The test directory was of course created by a program.) For years afterwards, that directory was the bane of file-tree-walking programs; it tested them to destruction.

注意,该目录必须包含条目。和. .,所以它可以说是253个文件(和2个目录),或者255个名称条目,而不是254个文件。这并不影响轶事的有效性,也不影响它所描述的仔细测试。

TPOP之前在 http://plan9.bell-labs.com/cm/cs/tpop和 http://cm.bell-labs.com/cm/cs/tpop但现在(2021-11-12)都坏了。 参见维基百科上的TPOP。

其他回答

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

$PathInvalidChars = [System.IO.Path]::GetInvalidPathChars() #36 chars

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

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

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

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

在Linux和其他与unix相关的系统下,传统上只有两个字符不能出现在文件或目录的名称中,那就是NUL '\0'和斜杠'/'。当然,斜杠可以出现在路径名中,分隔目录组件。

有传言说,史蒂文·伯恩(因“贝壳”而出名)有一个包含254个文件的目录,一个文件对应一个可以出现在文件名中的每个字母(字符代码)(不包括/,'\0';名字。当然是当前的目录)。它被用来测试伯恩外壳,并经常对备份程序等不小心的程序造成严重破坏。

其他人已经介绍了Windows文件名的规则,并提供了微软和维基百科的相关链接。

注意MacOS X有一个不区分大小写的文件系统。目前的版本似乎允许在文件名中使用冒号,尽管在历史上并不一定总是这样:

$ echo a:b > a:b
$ ls -l a:b
-rw-r--r--  1 jonathanleffler  staff  4 Nov 12 07:38 a:b
$

但是,至少在macOS Big Sur 11.7中,文件系统不允许文件名不是有效的UTF-8字符串。这意味着文件名不能由UTF-8中始终无效的字节组成(0xC0, 0xC1, 0xF5-0xFF),并且不能使用延续字节0x80..0xBF作为文件名中的唯一字节。给出的错误是92非法字节序列。

POSIX定义了一个可移植文件名字符集,包括:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 . _ -

坚持使用完全由这些字符组成的名称可以避免大部分问题,不过Windows仍然增加了一些复杂性。


1

It was Kernighan & Pike in ['The Practice of Programming'](http://www.cs.princeton.edu/~bwk/tpop.webpage/) who said as much in Chapter 6, Testing, §6.5 Stress Tests:

When Steve Bourne was writing his Unix shell (which came to be known as the Bourne shell), he made a directory of 254 files with one-character names, one for each byte value except '\0' and slash, the two characters that cannot appear in Unix file names. He used that directory for all manner of tests of pattern-matching and tokenization. (The test directory was of course created by a program.) For years afterwards, that directory was the bane of file-tree-walking programs; it tested them to destruction.

注意,该目录必须包含条目。和. .,所以它可以说是253个文件(和2个目录),或者255个名称条目,而不是254个文件。这并不影响轶事的有效性,也不影响它所描述的仔细测试。

TPOP之前在 http://plan9.bell-labs.com/cm/cs/tpop和 http://cm.bell-labs.com/cm/cs/tpop但现在(2021-11-12)都坏了。 参见维基百科上的TPOP。

我也有同样的需求,正在寻找推荐信或标准推荐信,偶然发现了这条线索。我目前在文件和目录名中应该避免的字符黑名单是:

$CharactersInvalidForFileName = {
    "pound" -> "#",
    "left angle bracket" -> "<",
    "dollar sign" -> "$",
    "plus sign" -> "+",
    "percent" -> "%",
    "right angle bracket" -> ">",
    "exclamation point" -> "!",
    "backtick" -> "`",
    "ampersand" -> "&",
    "asterisk" -> "*",
    "single quotes" -> "“",
    "pipe" -> "|",
    "left bracket" -> "{",
    "question mark" -> "?",
    "double quotes" -> "”",
    "equal sign" -> "=",
    "right bracket" -> "}",
    "forward slash" -> "/",
    "colon" -> ":",
    "back slash" -> "\\",
    "lank spaces" -> "b",
    "at sign" -> "@"
};

虽然唯一非法的Unix字符可能是/和NULL,但应该考虑到命令行解释。

例如,虽然在Unix中将文件命名为1>&2或2>&1是合法的,但在命令行中使用这样的文件名可能会被误解。

类似地,也可以将文件命名为$PATH,但当试图从命令行访问它时,shell将把$PATH转换为其变量值。

禁止文件名字符的“全面指南”在Windows上不起作用,因为它保留了文件名和字符。是的,像这样的角色 *”?还有一些名字是禁止使用的,但是有无数个名字是只由有效字符组成的,是禁止使用的。例如,空格和点是有效的文件名字符,但仅由这些字符组成的名称是禁止的。

Windows不区分大写字母和小写字母,因此如果已经存在名为a的文件夹,则不能创建名为a的文件夹。更糟糕的是,像PRN和CON这样看似允许的名字,以及许多其他的名字,是被保留和不允许的。Windows也有一些长度限制;在一个文件夹中有效的文件名如果移到另一个文件夹中可能会失效。的规则 命名文件和文件夹 都在微软文档里。

一般来说,不能使用用户生成的文本创建Windows目录名。如果您希望允许用户任意命名,则必须创建安全的名称,如A、AB、A2等,将用户生成的名称及其等效路径存储在应用程序数据文件中,并在应用程序中执行路径映射。

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