Windows和Linux目录名称中禁止使用哪些字符?
我知道/在Linux中是非法的,以下在Windows(我认为)是非法的*
.
"
/
\
[
]
;
|
=
,
我还有什么遗漏?
然而,我需要一个全面的指导,并且需要考虑到双字节字符。 连接到外部资源对我来说很好。
我需要首先使用可能包含禁止字符的名称在文件系统上创build一个目录,所以我打算用下划线replace这些字符。 然后我需要将这个目录及其内容写入一个zip文件(使用Java),所以有关zip目录的名字的任何额外的build议将不胜感激。
禁用文件名字符的“综合指南”在Windows上不起作用,因为它保留文件名和字符。 是的,禁止使用*
"
?
"
等字符,但是只有有效字符是禁止使用的无限制名称,例如空格和点是有效的文件名字符,但是只包含这些字符的名字是禁止的。
Windows不区分大写和小写字符,所以如果名称为a
的文件夹已经存在,则不能创build名为A
的文件夹。 更糟糕的是,像PRN
和CON
这样的看似允许的名字,以及其他许多名字,都是保留的,不允许的。 Windows也有几个长度限制; 在一个文件夹中有效的文件名如果移动到另一个文件夹可能会失效。 命名文件和文件夹的规则在MSDN上。
通常,您不能使用用户生成的文本来创buildWindows目录名称。 如果要允许用户命名他们想要的任何内容,则必须创build安全名称,如A
, AB
, A2
等,将用户生成的名称及其path等价物存储在应用程序数据文件中,然后在应用程序中执行path映射。
如果您绝对必须允许用户生成的文件夹名称,那么判断它们是否无效的唯一方法是捕获exception并假定名称无效。 即使这样也是充满危险的,因为拒绝访问,离线驱动器和驱动器空间的例外情况与可能为无效名称而抛出的情况重叠。 你正在打开一个巨大的伤害jar头。
1.)让我们先简单回答一下问题。
禁止打印的ASCII字符是:
的Linux / Unix:
/ (forward slash)
视窗:
< (less than) > (greater than) : (colon - sometimes works, but is actually NTFS Alternate Data Streams) " (double quote) / (forward slash) \ (backslash) | (vertical bar or pipe) ? (question mark) * (asterisk)
2.)不可打印的字符
如果您的数据来自允许不可打印字符的来源,那么还有更多要检查的内容。
的Linux / Unix:
0 (NULL byte)
视窗:
0-31 (ASCII control characters)
注意:虽然在Linux / Unix文件系统下使用文件名创build带有控制字符的文件是合法的, 但是用户处理这些文件可能是一场噩梦 。
3.)保留的文件名
以下文件名是保留的:
视窗:
CON, PRN, AUX, NUL COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9 LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9
4.)其他规则
视窗:
Filenames cannot end in a space or dot.
在Linux和其他与Unix相关的系统中,只有两个字符不能出现在文件或目录的名称中,而这些字符是NUL '\0'
和斜杠'/'
。 斜线当然可以出现在一个path名中,将目录组件分开。
有传闻1说,Steven Bourne('shell'的名声)有一个包含254个文件的目录,每个单个字母(字符代码)可以出现在文件名中。 它被用来testingBourne shell,并且经常对诸如备份程序之类的不经意的程序造成严重破坏。
其他人已经涵盖了Windows规则。
请注意,MacOS X具有不区分大小写的文件系统。
1 “编程实践”中的 Kernighan&Pike在第6章“testing”第6章“压力testing:
当Steve Bourne编写他的Unix shell(后来被称为Bourne shell)时,他创build了一个带有一个字符名称的254个文件的目录,每个字节值除了
'\0'
和斜杠之外都有一个名称,这两个字符不能出现在Unix文件名中。 他使用该目录进行模式匹配和标记化的所有testing。 (testing目录当然是由一个程序创build的。)多年以后,该目录是文件树行走程序的祸根; 它testing了它们的销毁。
那么,如果只是为了研究的目的,那么你最好的select是看这个维基百科条目的文件名 。
如果你想编写一个可移植的函数来validation用户input并创build文件名,那么最简单的答案就是不要 。 看一下像Perl的File :: Spec这样的可移植模块,就可以看到完成这样一个“简单”任务所需的所有跳跃。
您可以使用白名单 ,而不是创build黑名单。 所有事情都考虑在内,在文件或目录名称上下文中有意义的字符范围非常短,除非你有一些非常具体的命名要求,否则如果用户不能使用整个ASCII表,那么用户将不会对它持有它。
它不能解决目标文件系统中保留名称的问题,但是使用白名单可以更容易地从源头降低风险。
本着这种精神,这是一系列可以被认为是安全的字符:
- 字母(az AZ) – 如果需要,还需要Unicode字符
- 数字(0-9)
- 下划线(_)
- 连字符( – )
- 空间
- 点(。)
还有你希望允许的其他安全字符。 除此之外,您只需执行一些关于空格和点的附加规则 。 这通常是足够的:
- 名称必须包含至less一个字母或数字(以避免只有点/空格)
- 名称必须以字母或数字开头(避免前导点/空格)
这已经允许相当复杂和无意义的名字。 例如,使用这些规则,这些名称是可能的,并且在Windows / Linux中是有效的文件名:
-
A...........ext
-
B -.- .ext
从本质上讲,即使有这么less的白名单字符,你仍然应该决定什么是有意义的,并相应地validation/调整名称。 在我的一个应用程序中,我使用了与上面相同的规则,但是删除了任何重复的点和空格。
让Windows知道答案的简单方法是尝试通过资源pipe理器重命名文件,然后键入/input新名称。 Windows会popup一个消息框,告诉你非法字符的列表。
A filename cannot contain any of the following characters: \ / : * ? " < > |
截至2017年4月18日,在这个主题的答案中,没有简单的黑色或白色的字符和文件名列表,而且有很多回复。
我可以想出的最好的build议是让用户命名文件,但他喜欢。 当应用程序尝试保存文件时使用error handling程序,捕捉任何exception,假定文件名是责备(显然确保保存path是好的后),并提示用户一个新的文件名。 为了获得最好的结果,将这个检查过程放在一个循环中,直到用户正确或放弃。 为我工作最好(至less在VBA)。
示例VBA代码:( 将在今天晚些时候添加)
对于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
我有同样的需求,并寻找推荐或标准的参考和碰到这个线程。 我目前在文件和目录名称中应该避免的字符黑名单是:
$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
,尽pipe应该包括对命令行解释的一些考虑。
例如,虽然在Unix中命名文件1>&2
或2>&1
可能是合法的,但是在命令行上使用这样的文件名可能会被误解。
同样,可以命名文件$PATH
,但是当试图从命令行访问文件时,shell会将$PATH
转换为其variables值。
在Unix shell中,你可以用单引号引用几乎所有的字符。 除了单引号本身,你不能expression控制字符,因为\
不扩展。 在引用的string中访问单引号是可能的,因为你可以用单引号和双引号连接string,比如'I'"'"'m'
,可以用来访问名为"I'm"
的文件报价也可以在这里)。
所以你应该避免所有的控制字符,因为它们太难以进入shell。 其余部分仍然很有趣,特别是以短划线开头的文件,因为大多数命令都将这些选项作为选项读取,除非您有两个破折号--
之前,或者用./
指定它们,这也隐藏了开始部分。
如果你想要很好,不要使用shell和典型命令使用的任何字符作为语法元素,有时候依赖于位置,所以,例如,你仍然可以使用-
,但不能作为第一个字符; 同样.
,只有当你的意思是(“隐藏文件”)时,才可以将其用作第一个字符。 当你的意思是,你的文件名是VT100转义序列;-),所以一个ls乱码的输出。
在Windows中创buildInternet快捷方式时,要创build文件名,它将跳过非法字符,正斜杠除外,该斜杠将转换为负号。