创建文件名时,冒号(:)显示为正斜杠(/)

我正在使用日期和时间标记我正在创建的新文件,但是当我查看文件时,冒号是正斜杠。 我正在使用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 

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

编辑:经过一番搜索后, 这篇USENIX论文描述了正在发生的事情。 他们明显使用的规则是这样的:

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

虽然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的开发人员问答#1392以及有关在AppleScript中指定路径的说明,以便进行更多讨论。

(还有一些其他差异。如果unix路径以分隔符(“/”)开头,则绝对路径是绝对的,绝对路径从根卷的顶部开始。如果OS 9路径无法启动,则它是绝对路径使用分隔符,绝对OS 9路径以卷名开头。因此,unix路径“/ tmp / foo:bar”相当于OS 9路径“Macintosh HD:tmp:foo / bar”。)

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

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

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

更新:正如Konrad Rudolph所指出的那样,Go Cap文件夹的行为已经改变了El Capitan,我不再有任何方法可以使用它来获取包含有争议角色的文件夹。

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

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

因为这个特殊的问题不是bug,也不是Ruby的控制,而是Apple的,我说它根本不是Ruby问题,它是一个可视化问题,如果你想让文件名类似于Finder相应的显示代码。