文件名中允许的字符都有那些?

我在哪里可以找到文件名中允许的字符列表,取决于操作系统? (例如,在Linux上,字符:被允许在文件名中,但在Windows上不允许)

262549 次浏览

你应该从维基百科的文件名页开始。它有一个相当大的表(文件名限制的比较),列出了相当多文件系统的保留字符。

它也有关于每个文件系统的大量其他信息,包括保留文件名,如MS-DOS下的CON。我之所以提到这一点,只是因为有一次我把一个包含文件从const.h缩短为con.h,并花了半个小时弄清楚为什么编译器挂起。

结果是DOS 忽略了扩展设备,因此con.h与输入控制台con完全相同(当然,这意味着编译器在继续之前等待我输入头文件)。

好的,如果你只关心主要播放器的文件系统,那么看看文件系统比较:

  • Windows (FAT32, NTFS):除NUL\/:*?"<>|之外的任何Unicode。同时,\0。
  • Mac(HFS, HFS+):除:/外的任何有效Unicode
  • Linux(ext[2-4]):除NUL/外的任何字节

所以任何字节除了NUL\/:*?"<>|你不能有文件/文件夹调用\0或\1(当然)没有控制字符。

在Windows操作系统上创建一个文件,并在文件名中给它一个像\这样的无效字符。结果,你会得到一个弹出窗口,所有的无效字符在一个文件名。

enter image description here

更准确地说,对于MacOS X(现在称为MacOS), Finder中的/被解释为Unix文件系统中的:

这样做是为了向后兼容苹果从经典Mac操作系统。

在Finder中的文件名中使用/是合法的,在终端中查看相同的文件,它将显示:

它也可以反过来工作:你不能在终端的文件名中使用/,但是:是可以的,并且会在Finder中显示为/

有些应用程序可能会更加严格,禁止使用这两个字符,以避免混淆,或者因为它们保留了以前经典Mac OS的逻辑,或者为了平台之间的名称兼容性。

下面是在python中清除文件名的代码。

import unicodedata


def clean_name(name, replace_space_with=None):
"""
Remove invalid file name chars from the specified name


:param name: the file name
:param replace_space_with: if not none replace space with this string
:return: a valid name for Win/Mac/Linux
"""


# ref: https://en.wikipedia.org/wiki/Filename
# ref: https://stackoverflow.com/questions/4814040/allowed-characters-in-filename
# No control chars, no: /, \, ?, %, *, :, |, ", <, >


# remove control chars
name = ''.join(ch for ch in name if unicodedata.category(ch)[0] != 'C')


cleaned_name = re.sub(r'[/\\?%*:|"<>]', '', name)
if replace_space_with is not None:
return cleaned_name.replace(' ', replace_space_with)
return cleaned_name

对于“English locale”文件名,这很有效。我用这个来消毒上传的文件名。文件名并不意味着要链接到磁盘上的任何东西,它是在文件下载时使用的,因此没有路径检查。

$file_name = preg_replace('/([^\x20-~]+)|([\\/:?"<>|]+)/g', '_', $client_specified_file_name);

基本上,它会删除Windows和其他操作系统中所有不可打印和保留的字符。你可以很容易扩展模式来支持其他地区和功能。

与其试图识别所有不需要的字符, 除了可接受的字符,你可以寻找任何东西。这是一个除posix字符以外的任何字符的正则表达式:

cleaned_name = re.sub(r'[^[:alnum:]._-]', '', name)

我采取了不同的方法。我不检查字符串是否只包含有效字符,而是查找无效/非法字符。

注意:我需要验证一个路径字符串,而不是一个文件名。但如果你需要检查文件名,只需将/添加到集合中。

def check_path_validity(path: str) -> bool:
# Check for invalid characters
for char in set('\?%*:|"<>'):
if char in path:
print(f"Illegal character {char} found in path")
return False
return True