如何在Haskell中获取可执行文件的目录?

7
我有一个可以读写文本文件的程序,该文件与可执行文件位于同一目录下。为了访问该文件,我调用 readFile "./file.txt"
当我在该目录中运行可执行文件时,它可以正常工作。但是,如果我使用cd命令切换到其他目录并运行可执行文件(因为它在我的路径上),Haskell会尝试从终端的工作目录获取file.txt文件。如何使Haskell从可执行文件所在的位置而不是我的工作目录中访问file.txt?我不想硬编码绝对路径,因为我希望该可执行文件具有一定的可移植性。
4个回答

9

正确的做法是在您的.cabal文件的data-files字段中列出file.txt,并使用getDataFileName来检索它。有关前缀独立性,请参见cabal文档


5
为什么不将文件存储在官方应用目录中?这样无论当前目录是什么都不会有影响。(请参见getAppUserDataDirectory。)
System.Directory中还有其他有用的目录和便捷的文件系统实用程序。从跨平台的角度来看,它知道根据您的操作系统应该将东西放在哪里。
推理:
如果将工作数据存储在可执行文件所在的目录中,则只有具有该目录写权限的人才能正确运行您的程序。只有超级用户才能在像/usr/local/bin这样的目录中写入,只有管理员才能在C:\Program Files\中写入。使用用户应用程序目录,任何人都可以运行应用程序,因为应用程序数据目录特定于用户且可由其编写,因此这是一个好的做法。
就我个人而言,我不喜欢应用程序在我的主用户区域中杂乱无章地存储配置数据,但是我希望应用程序建议我的用户区域作为保存一些自己内容的第一选择(getHomeDirectory)。我建议使用用户应用程序数据目录,因为您建议使用可执行文件所在的目录,所以它听起来像是配置数据。

不完全是我要找的,但这是一个更为简洁的解决方案。 - Sam Stern

5

函数getExecutablePath可以实现您的要求。不幸的是,它只在最新发布的GHC 7.6.1中添加到System.Environment中,尚未被纳入Haskell平台

编辑:具有此功能的新Haskell平台已经发布。


0
#!/usr/bin/env stack
{- stack
   script
   --nix
   --nix-packages zlib
   --resolver lts-14.17
   --package turtle
   --package protolude
   --package directory
-}

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}

module Playground where

import Protolude hiding (find)
import Turtle
import System.Directory
import Data.String

main :: IO ()
main = do
  let thisScriptAbsFilePath :: String = __FILE__
  let thisScriptAbsFilePath' :: Turtle.FilePath = decodeString thisScriptAbsFilePath
  let projectRoot :: Turtle.FilePath = directory thisScriptAbsFilePath'
  print projectRoot
  return ()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接