【问题标题】:What character sequence should I not allow in a filename?我不应该在文件名中允许什么字符序列?
【发布时间】:2011-01-19 05:45:35
【问题描述】:

我在测试后发现 linux 允许文件名中的任何字符,除了/ 和 null (\0)。那么我不应该在文件名中允许什么序列?我听说领先的- 可能会混淆一些命令行程序,这对我来说并不重要,但是如果他们决定收集一堆文件并用一些 GNU 程序过滤它可能会打扰其他人。

有人建议我删除前导和尾随空格,我打算这样做只是因为通常用户并不意味着有前导/尾随空格。

可能存在哪些问题序列以及我应该考虑不允许哪些序列? 为了方便起见,我还在考虑不允许在 Windows 中使用非法字符。我想我可能不允许在开头使用破折号(破折号是合法的窗口字符)

【问题讨论】:

标签: linux command-line filenames


【解决方案1】:

您的问题有点令人困惑,因为您详细讨论了 Linux,但是在对另一个答案的评论中,您说您正在生成文件名供人们下载,这大概意味着您完全无法控制文件系统和文件将存储在哪个操作系统上,使 Linux 完全无关紧要。

出于此答案的目的,我将假设您的问题是错误的并且您的评论是正确的。

当今使用的绝大多数操作系统和文件系统大致分为三类:POSIX、Windows 和 MacOS。

POSIX 规范非常清楚保证在所有 POSIX 系统之间可移植的文件名是什么样的。您可以使用的字符在Section 3.276 (Portable Filename Character Set) of the Open Group Base Specification 中定义为:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789._-
您可以依赖的最大文件名长度在Section 13.23.3.5 (<limits.h> Minimum Values) 中定义为14。 (相关常量为_POSIX_NAME_MAX。)

因此,最长 14 个字符且仅包含上面列出的 65 个字符的文件名可以在所有 POSIX 兼容系统上安全使用,它为您提供 24407335764928225040435790 组合(或大约 84 位)。

如果您不想惹恼您的用户,您应该再添加两个限制:不要以破折号或点开头的文件名。以点开头的文件名通常被解释为“隐藏”文件,除非明确要求,否则不会显示在目录列表中。以破折号开头的文件名可能会被许多命令解释为一个选项。 (旁注:令人惊讶的是有多少用户不知道 rm ./-rfrm -- -rf 技巧。)

这让你有 23656340818315048885345458 组合(仍然是 84 位)。

Windows 对此添加了一些新限制:文件名不能以点结尾并且文件名不区分大小写。这将字符集从 65 个字符减少到 39 个字符(第一个字符 37 个,最后一个字符 38 个)。不加任何长度限制,windows可以处理14个字符就好了。

这将可能的组合减少到 17866587696996781449603(73 位)。

另一个限制是 Windows 将最后一个点之后的所有内容视为表示文件类型的文件扩展名。如果您想避免潜在的混淆(例如,如果您为文本文件生成像 abc.mp3 这样的文件名),您应该完全避免使用点。

您仍然有 13090925539866773438463 个组合(73 位)。

如果您必须担心 DOS,则应用附加限制:文件名由一或两部分组成(由点分隔),其中两部分都不能包含点。第一部分的最大长度为 8,第二部分为 3 个字符。同样,第二部分通常保留以指示文件类型,只剩下 8 个字符。

现在您有 4347792138495 个可能的文件名或 41 位。

好消息是,您可以使用 3 个字符的扩展名来真正正确指示文件类型,而不会违反 POSIX 文件名限制 (8+3+1 = 12 p>

如果您希望您的用户能够将文件刻录到使用 ISO9660 级别 1 格式化的 CD-R 上,那么您必须禁止在任何地方使用连字符,而不仅仅是第一个字符。现在,剩下的字符集看起来像

ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789_
为您提供 3512479453921 种组合(41 位)。

【讨论】:

  • 惊人的答案。是的,我的问题有点奇怪。我将文件存储为他们的 ID,我可以检查用户使用的操作系统以自定义有效的文件名,并将名称作为数据库中的标题。我从来不知道 CD 上不允许使用连字符。 posix 有点限制(并且不允许 unicode!),我需要支持 unicode。所以我将禁止连字符、点和非法窗口字符。提供一个限制较少的选项(或在 linux 上使用),并确保我检查了我的工作,所以没有什么会阻止它刻录到 CD 上(希望可以在默认命名的主操作系统上工作)。
  • @acidzombie24:压倒性的大多数 CD 都使用 ISO9660 Level 2 进行格式化,确实允许使用连字符和更长的文件名。连字符仅在 ISO9660 Level 1 上是非法的,实际上没有人使用。我只是为了完整性而提到它。另请注意,我没有说任何关于 MacOS 的内容,只是因为我对它了解得不够多。同样,Apple 实际上已经消除了 OSX 中几乎所有古老的 MacOS 限制,因此它可能不是很相关。
  • BTW POSIX 确实 允许 UTF-8 Unicode;它只要求 minimum 字符集必须对 POSIX 兼容有效。大多数 POSIX 文件系统允许任何不包含 '/' 或 '\0' 的字节序列,但可移植应用程序不应依赖此。
  • 还有某些序列是各种操作系统不允许的,即使它们遵循规则。例如,Windows 上不允许使用“CON”。
【解决方案2】:

我建议使用一组白名单字符。一般来说,文件名中的符号会惹恼人们。

一定要允许人们使用 az 0-9 和 > 0x80 的 unicode 字符,但不允许使用任意符号,例如 & 和 ,会造成很多麻烦,以及在不适当的地方使用句号。

我认为允许安全的 ASCII 符号是:句号下划线连字符

在文件名中允许任何其他 ascii 符号是自找麻烦。

文件名也不应该以 ascii 符号开头。文件名中的空格策略很棘手,因为用户可能希望能够使用它们,但有些文件名显然很愚蠢(例如那些以空格开头的文件名)

【讨论】:

    【解决方案3】:

    您是否正在开发一个必须要求用户自己创建文件的应用程序?如果这就是您正在做的事情,那么您可以在您的应用程序中设置规则。 (例如,只允许 [a-zA-Z0-9_.] 并拒绝其余的特殊字符。)这执行起来要简单得多。

    【讨论】:

      【解决方案4】:

      由于您似乎主要对 Linux 感兴趣,所以要避免的一件事是(典型的)shell 会尝试解释的字符,例如,作为通配符。如果您坚持,您可以创建一个名为“*”的文件,但您可能会有一些不太欣赏它的用户。

      【讨论】:

        【解决方案5】:

        urlencode 将所有字符串用作文件名,您只需要担心长度。 This answer 可能值得一读。

        【讨论】:

          【解决方案6】:

          我会将“有效”的决定留给操作系统和文件系统驱动程序。让用户输入他们想要的任何内容,然后传递。以适当的方式处理来自操作系统的错误。例外是我认为去掉前导和尾随空格是合理的。如果人们想要创建带有嵌入空格或前导破折号或问号的文件名,并且他们选择的文件系统允许这样做,那么您不应该尝试阻止它们。

          可以在不同的挂载点(或 Windows 中的驱动器)挂载不同的文件系统,这些文件系统对文件名中的合法字符有不同的规则。在您的应用程序中处理此类事情将比必要的工作量大得多,因为操作系统已经为您完成了。

          【讨论】:

          • 我实际上是在为用户生成文件名,以便从网络浏览器进行 DL。保存为并告诉您文件名无效会很烦人。也因为 linux 确实允许它并不意味着它应该的一切(显然有些事情激怒了命令行工具,但我是二手的)。
          猜你喜欢
          • 2011-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-01
          • 2017-09-02
          • 1970-01-01
          • 2012-11-07
          • 2020-03-30
          相关资源
          最近更新 更多