【问题标题】:Colon (:) appears as forward slash (/) when creating file name创建文件名时冒号 (:) 显示为正斜杠 (/)
【发布时间】:2016-05-22 00:53:16
【问题描述】:

我正在使用日期和时间来标记我正在创建的新文件,但是当我查看文件时,冒号是正斜杠。我正在使用 10.7+ 的 Mac 上开发

这是我正在使用的代码:

 File.open("#{time.hour} : 00, #{time.month}-#{time.day}-#{time.year}", "a") do |mFile|
        mFile.syswrite("#{pKey} - #{tKey}: \n") 
        mFile.syswrite("Items closed: #{itemsClosed} | Total items: #{totalItems} | Percent closed: % #{pClosed} \n") 
        mFile.syswrite("\n")
        mFile.close
     end

这是输出(假设时间是下午 1 点):

13 / 00, 11-8-2012

为什么会发生这种情况,我该如何解决?我希望输出是:

13:00, 11-8-2012

【问题讨论】:

标签: ruby macos


【解决方案1】:

曾几何时,在 Mac OS X 之前,: 是目录分隔符,而不是 /。显然 OS X 10.7 仍在尝试修复这样的程序。如果您真的需要:,我不知道您如何解决这个问题。我会省略它:-)。

编辑:经过更多搜索this USENIX paper 描述了正在发生的事情。他们使用的规则显然是这样的:

另一个明显的问题是 HFS+(冒号,':')和 UFS 之间的路径分隔符不同 (斜线,'/')。这也意味着 HFS+ 文件名可能包含斜杠字符而不是 冒号,而 UFS 文件名则相反。这很容易解决,尽管它 涉及来回转换字符串。内核 VFS 中的 HFS+ 实现 层在读取和写入磁盘时将冒号转换为斜线,反之亦然 格式。所以在磁盘上,分隔符是一个冒号,但在 VFS 层(因此任何 在它和内核(例如 libc)之上是一个斜线。然而,传统的 Mac OS 工具包需要冒号,因此在 BSD 层之上,核心 Carbon 工具包还有另一个 翻译。结果是 Carbon 应用程序看到冒号,而其他人看到 斜线。这可以在文件名的罕见情况下创建用户可见的精神分裂症 包含冒号字符,在 Carbon 应用程序中显示为斜线字符,但 BSD 程序和 Cocoa 应用程序作为冒号。

【讨论】:

  • 有趣。你知道我该如何解决它以获得我想要的输出吗?
  • 冒号在 OS X (/HFS+) 和 Windows (/NTFS) 下都是非法的文件名字符;我不确定您认为这是 OS X 为保持向后兼容性所做的挥之不去的尝试是否准确。
  • @Tommy 在 Windows 上,它只会导致无效操作(如果不是驱动器限定符的一部分或 NTFS 中的 ADS);不是无声的转换..
  • @Tommy 我从来没有说过: 是一个文件名字符。我也不完全确定是 OS X 将其转换为 /。但是有些东西会记住过去并试图修复它,我认为 OS X 比 Ruby 更强大。
  • 来自 Mac OS 上的 ~,如果我在 Finder 中得到一个名为 touch Desktop:foo 的文件,并在命令行中调用 Desktop:foo。这是 Apple 在 Finder 中的小手,而不是它下面的操作系统中的任何东西。请记住,Finder 负责文件系统的可视化。操作系统负责管理它。
【解决方案2】:

虽然 OS X“是”一个 unix 操作系统,但它也从 Mac OS 9 派生了相当多的代码、API、标准等。在 unix 中,文件路径用“/”分隔元素,“:”是允许在单个文件和目录的名称中。在 Mac OS 9 中,情况正好相反:文件路径在元素之间使用“:”,而在单个文件名中允许使用“/”。当 Apple 开发 OS X 时,他们最终不得不支持一些使用 unix 样式文件路径的 API,以及一些使用 OS 9 样式路径的 API,并且它们都必须能够在同一个文件系统上工作。

他们所做的是根据上下文交换分隔符和允许的字符。如果您编写(/运行)一个使用 unix API 访问文件系统的程序,您将看到文件名中带有冒号和斜线分隔路径元素的文件。如果您编写(/运行)一个使用旧的 OS 9 API(或其衍生产品)的程序,您将看到文件名中带有斜杠和分隔路径元素的冒号。更多讨论请参见Apple's developer Q&A #1392notes on specifying paths in AppleScript

(还有一些其他区别。unix 路径以定界符(“/”)开头是绝对路径,绝对路径从根卷的顶部开始。OS 9 路径如果 不以分隔符开头,绝对 OS 9 路径以卷名开头。因此,unix 路径“/tmp/foo:bar”等效于 OS 9 路径“Macintosh HD:tmp :foo/bar"。)

那么,文件名中的真正是哪个字符,是斜线还是冒号?好吧,文件名是一个相当抽象的东西,但是如果您询问实际存储在磁盘上的字节......如果它位于 HFS+(又名 Mac OS 扩展)卷上,则它存储在一个文件系统中旨在与 OS 9(好吧,技术上是 Mac OS 8.1)API 一起使用,因此它允许斜杠但禁止冒号,因此在 HFS+ 卷上,文件将“真正”在名称中有斜杠。 OTOH,如果您将文件存储在 unixish 卷上,它将使用 unix 约定存储,并且“真正”的名称中有一个冒号。但区别并不重要,除非您从磁盘读取原始字节或编写文件系统驱动程序......

最后,为什么 Finder 将有争议的文件名字符显示为斜杠而不是冒号?我很确定这主要是惯性。 Finder 对此甚至不完全一致,因为如果您使用其转到文件夹选项 (Command-Shift-G) 并输入“/Users/Shared”,它会将其视为 unix 路径。如果你输入“Macintosh HD:Users:Shared”,它不知道你在说什么。此外,如果您运行touch /tmp/foo:bar,请尝试使用转到文件夹:

  • 输入“/tmp/foo:bar”有效。
  • 输入“/tmp/fo”,然后按 Tab 将自动补全到“/tmp/foo/bar/”,这样可以。
  • 输入“/tmp/foo/bar/”失败,即使它与自动完成功能完全相同。
  • 输入“/tmp/foo”,然后按 Tab 键自动完成到“/tmp/foo/”,它不能再自动完成,而且根本不起作用。

更新:正如 Konrad Rudolph 所指出的,从 El Capitan 开始,转到文件夹的行为已经改变,我不再有任何方法可以使用它来访问包含有争议角色的文件夹。

【讨论】:

  • 那么touch ":..:bar"会在父目录下创建文件吗?
  • @user2284570:不,touch 使用 unix API,因此它将“:”视为文件名的一部分,而不是路径分隔符。假设您的当前目录是 /Users/fred/Documents。它将创建一个文件,unix API 将其视为“/Users/fred/Documents/:..:bar”。另一方面,Mac OS 9 派生的 API 会将其视为“Macintosh HD:Users:fred:Documents:/../bar”。
  • 有趣的是,El Capitan 显然又一次改变了 Finder 的语义……现在“转到文件夹”不再支持导航到名称中包含斜杠/冒号的文件夹根本。您帖子末尾列举的所有方法都不起作用。
【解决方案3】:

为了在处理File 名称、路径和各种操作系统时尽可能避免出现问题,您确实应该利用内置的File 方法,例如joindirname、@987654325 @、extnamesplit。他们试图避免系统依赖,并尝试为您提供一种跨平台生成有效文件名的编程方式。

当 Apple 使用旧的 Macintosh 操作系统时,这个问题要严重得多。迁移到 Mac OS 有所帮助,因为他们放弃了使用 : 作为分隔符,但是那些手动构建文件名的人发现代码破坏,因为它生成了错误的分隔符,而利用库解决了这个问题。

因为这个特殊问题不是错误,也不是 Ruby 的控制,而是 Apple 的,所以我想说这根本不是 Ruby 问题,这是一个可视化问题,如果您希望文件名类似于 Finder相应地显示代码。

【讨论】:

    猜你喜欢
    • 2011-06-05
    • 1970-01-01
    • 2016-01-19
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    相关资源
    最近更新 更多