Windows 在每个操作系统的文件路径中是否有任何非法字符?
是否有任何字符保证不会出现在Windows或Unix/Linux/OS X上的任何文件路径中Windows 在每个操作系统的文件路径中是否有任何非法字符?,windows,unix,character,filepath,Windows,Unix,Character,Filepath,是否有任何字符保证不会出现在Windows或Unix/Linux/OS X上的任何文件路径中 我之所以需要它,是因为我想将几个文件路径合并成一个字符串,然后稍后再将它们分开。您可以使用换行符,或者如果愿意,可以使用CR(十进制代码13)或LF(十进制代码10)。这是否合适取决于您对向用户显示连接字符串的要求——使用这种方法,它将在单独的行上打印其部分——这可能是非常好的,也可能是非常坏的(或者您可能不在乎……) 如果需要在单行上打印连接的字符串,请编辑问题以指定此附加要求;然后我们就可以开始了。
我之所以需要它,是因为我想将几个文件路径合并成一个字符串,然后稍后再将它们分开。您可以使用换行符,或者如果愿意,可以使用CR(十进制代码13)或LF(十进制代码10)。这是否合适取决于您对向用户显示连接字符串的要求——使用这种方法,它将在单独的行上打印其部分——这可能是非常好的,也可能是非常坏的(或者您可能不在乎……)
如果需要在单行上打印连接的字符串,请编辑问题以指定此附加要求;然后我们就可以开始了。哈里·约翰斯顿在评论中写道: 这类问题的通用解决方案是在连接文件路径之前对其进行编码。例如,如果处理单字节字符串,可以将其转换为十六进制字符串;所以“你好”变成了“68656C6F”。(显然这不是最有效的解决方案!) 这是绝对正确的。请不要试图对文件名和保留字符做任何“棘手”的事情,因为它最终会在一些奇怪的情况下崩溃,而您的继任者将花很长时间试图修复损坏 事实上,如果您试图实现可移植性,我强烈建议您不要尝试创建任何文件名,包括除
[a-z0-9.]
以外的任何字符。(考虑Windows和OS X上的通用文件系统都可以在不区分大小写的模式下运行,其中FooBar.txt
和FooBar.txt
是相同的标识符。)
实际使用的一种非常紧凑的编码方案是制作一个“白名单集”,如[A-z0-9\]
,并将“白名单集”之外的任何字符ch
编码为printf(“\u2x”,ch)
。所以hello.txt
变成hello\u 2etxt
,而hello\u world.txt
变成hello\u 5fworld\u 2etxt
。
由于每个
都是转义的,因此可以使用double-
作为分隔符:在Unix上,编码字符串hello\u 2etxt\uuu\u再见\uuuuu2e\u 2e
唯一地标识文件名列表['hello.txt'、'bye'、'..]
,文件名中只允许有两个字符;斜杠和空(零)字节。不允许使用斜杠,因为它将路径的组件彼此分隔开;空值,因为它标记名称的结尾。因此,路径名中唯一不允许的字符是空字节。我不知道有哪种操作系统允许文件名中包含空字节;因此,通过reductio ad absurdam,在每个O/S上的文件路径中唯一非法的字符是空字节。大多数人在大多数情况下不在文件名中使用控制字符,但它们可以出现。@JonathanLeffler:Windows本机API不使用以null结尾的字符串,因此null至少可能是一个合法字符。我不确定NTFS驱动程序是否真的允许这样做。实际上,这可能并不重要。:-)@callum:这类问题的一般解决方案是在加入文件路径之前对其进行编码。例如,如果处理单字节字符串,可以将其转换为十六进制字符串;所以“你好”变成了“68656C6F”。(显然这不是最有效的解决方案!)@HarryJohnston:如果Windows上的文件名中允许使用NUL字节,那么(a)我很惊讶,(b)在Windows和类似Unix的系统上,没有任何字符保证不会出现在任何文件路径中。@JonathanLeffler:我刚刚尝试过这个方法,在NTFS卷上,尝试为文件命名并嵌入null被拒绝。我相信这是特定于文件系统的,所以理论上,在备用文件系统中可以允许嵌入null。(但是,似乎不太可能存在这样的文件系统,或者至少不在生产环境中!)恕我直言,虽然这个答案涵盖了常见情况,但Unix中的文件名中允许使用换行符。取决于文件名中没有换行符,最终将中断。这就是为什么许多GNU实用程序现在有一个选项,使用空字节作为文件列表的记录分隔符;它是唯一不能出现在路径名中的字符,因此它是绝对安全的。(请参见GNUfind
with-print0
,xargs
with-0
,sort
with-z
等。)