我有一个程序可以读取和写入与可执行文件位于同一目录中的文本文件。要访问该文件,请致电readFile "./file.txt"
当我从它所在的目录中运行可执行文件时,这是有效的。但是,如果我cd
到另一个目录并运行可执行文件(它在我的路径上),Haskell会尝试从终端的工作目录中获取file.txt
。如何让Haskell从可执行文件的位置访问file.txt
而不是我的工作目录。我不想硬编码绝对路径,因为我希望可执行文件有点可移植。
答案 0 :(得分:8)
执行此操作的正确方法是在file.txt
文件的data-files
字段中列出.cabal
,然后使用getDataFileName
进行检索。有关前缀独立性,请参阅cabal documentation。
答案 1 :(得分:5)
为什么不将文件存储在官方的应用程序目录中?那么当前目录是什么并不重要。 (见getAppUserDataDirectory。)
System.Directory中还有其他有用的目录和方便的文件系统实用程序。它是跨平台的,因为它根据你的操作系统知道应该去哪里。
推理:
如果将工作数据存储在与可执行文件相同的目录中,则只有在该目录中具有写入权限的人才能正确运行您的程序。只有超级用户才能写入/usr/local/bin
等目录,只有管理员才能写入C:\Program Files\
。使用User Application Directory,任何人都可以运行应用程序,因为应用程序数据目录特定于用户并且可由他们写入,因此这就是为什么这是一个好习惯。
就个人而言,我不喜欢应用程序使配置数据混乱我的主用户区,但是做想要应用程序,所以建议我的用户区域作为保存我自己内容的第一个猜测({ {3}})。我建议用户应用程序数据目录,因为你建议了可执行文件的目录,所以它听起来像配置数据。
答案 2 :(得分:4)
函数getExecutablePath
可以满足您的要求。不幸的是,它刚刚在刚发布的GHC 7.6.1中添加到System.Environment
,尚未纳入Haskell平台。
编辑:此功能的新Haskell平台已经发布。
答案 3 :(得分: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 ()