【问题标题】:Haskell Implement Unix "touch" commandHaskell 实现 Unix“触摸”命令
【发布时间】:2017-02-03 04:07:44
【问题描述】:

我正在尝试从 unix 命令行实现 touch 命令,但似乎我的最后一行引发了异常:** Exception: ~/.todo: openFile: does not exist (No such file or directory)

main = touch "~/.todo"

touch :: FilePath -> IO ()
touch name = do
  exists <- doesFileExist name
  unless exists $ appendFile name ""

如果有任何特定于操作系统的行为,我正在从 macOS Sierra 进行测试。

我觉得这个错误很奇怪,因为openFile 的文档指出

如果文件不存在并且打开以输出,则应将其创建为新文件。

关于如何解决此问题的任何建议?

编辑:根据@chi,touch 命令应该总是打开文件,即使它已经存在,因为它会更新文件的最后修改日期。

touch :: FilePath -> IO ()
touch name = appendFile name ""

【问题讨论】:

  • 我使用此代码成功地触摸了许多文件。有没有可能你有一个奇怪的 cwd?
  • 顺便说一下,touch 也经常用于更新现有文件的时间戳。
  • openFile 引发了异常,但您的代码 sn-p 不包括该异常。你能更新它以包含它吗?
  • 另外,为了强调您的引用:“如果文件不存在并且它被打开以输出,则应该创建它”。没有看到openFile,我猜你可能没有用正确的模式打开它。
  • FilePath与操作系统的文件路径概念相同,可以是绝对的也可以是相对的,但不能用~表示你的主目录,因为那是一个shell特征。如果您使用的文件名真的只是file.dat,那么只有当您的代码的当前工作目录已被删除或类似(@haoformayor 所说的)时,该错误才有意义。

标签: unix haskell command-line


【解决方案1】:

使用unix 包中的touchFile (System.Posix.Files.ByteString)。


appendFile name "" touch 一样工作;当要追加的字符串为空时,appendFile 是空操作。

您可以通过在文件前后运行stat 并比较修改时间来确认这一点。

【讨论】:

    【解决方案2】:

    以后请粘贴您正在使用的所有导致错误的代码。这包括导入和调用。在您的情况下,您似乎正在运行带有外壳扩展字符的东西:

    *Main> touch "~/foobar"
    *** Exception: ~/foobar: openFile: does not exist (No such file or directory)
    

    ~ 通常由 shell 扩展(还有一个 C 库可以为您进行重写)。大多数语言实际上将其解释为路径的文字部分...但 ~ 目录可能不存在,或者该符号甚至可能无效,具体取决于您的平台。

    尝试一个有效的文件路径:

    *Main> touch "/tmp/thisfile"
    *Main>
    Leaving GHCi.
    % ls -l /tmp/thisfile
    -rw-rw-r--. 1 theuser theuser 0 Feb  3 12:51 /tmp/thisfile
    

    【讨论】:

    • 您对我的错误是正确的。我曾怀疑这是错误,但忘记重新启动我的 ghci 会话。
    猜你喜欢
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 2016-12-30
    相关资源
    最近更新 更多