【问题标题】:How to get directory of executable in Haskell?如何在 Haskell 中获取可执行文件的目录?
【发布时间】:2012-09-11 01:36:19
【问题描述】:
我有一个程序可以读取和写入与可执行文件位于同一目录中的文本文件。要访问该文件,我调用readFile "./file.txt"
当我从它所在的目录中运行可执行文件时,这有效。但是,如果我 cd 到另一个目录并运行可执行文件(它在我的路径上),Haskell 会尝试从我终端的工作目录中获取 file.txt。如何让 Haskell 从可执行文件的位置而不是我的工作目录访问 file.txt。我不想硬编码绝对路径,因为我希望可执行文件具有一定的可移植性。
【问题讨论】:
标签:
haskell
io
readfile
working-directory
【解决方案1】:
执行此操作的正确方法是在您的.cabal 文件的data-files 字段中列出file.txt,并使用getDataFileName 检索它。前缀独立性见cabal documentation。
【解决方案2】:
函数getExecutablePath 可以满足您的要求。不幸的是,它仅在刚刚发布的 GHC 7.6.1 中添加到 System.Environment,尚未合并到 Haskell 平台中。
编辑:具有此功能的较新的 Haskell 平台已经发布。
【解决方案3】:
为什么不将您的文件存储在官方应用程序目录中?那么当前目录是什么都没有关系。 (见getAppUserDataDirectory。)
System.Directory 中还有其他有用的目录和方便的文件系统实用程序。它是跨平台的,因为它知道根据你的操作系统应该去哪里。
推理:
如果您将工作数据存储在与可执行文件相同的目录中,则只有在该目录中具有写入权限的人才能正确运行您的程序。只有超级用户可以写入/usr/local/bin 等目录,并且只有管理员可以写入C:\Program Files\。使用用户应用程序目录,任何人都可以运行应用程序,因为应用程序数据目录是特定于用户的并且可由他们写入,因此这是一种好的做法。
就我个人而言,我不喜欢应用程序将我的主要用户区域与配置数据混淆,但确实希望应用程序因此建议我的用户区域作为第一个猜测来保存我自己的一些内容(@ 987654323@)。我建议了用户应用程序数据目录,因为您建议了可执行文件的目录,所以听起来像配置数据。
【解决方案4】:
#!/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 ()