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

问题描述 投票:4回答:4

我有一个程序,该程序读写可执行文件所在目录中的文本文件。要访问该文件,我调用readFile "./file.txt"

当我从可执行文件所在的目录中运行可执行文件时,此方法有效。但是,如果我cd到另一个目录并运行可执行文件(在我的路径上),Haskell会尝试从终端的工作目录中获取file.txt。如何使Haskell从可执行文件而不是我的工作目录的位置访问file.txt。我不想对绝对路径进行硬编码,因为我希望可执行文件具有一定的可移植性。

haskell io readfile working-directory
4个回答
5
投票

为什么不将文件存储在正式的应用程序目录中?然后,当前目录是什么都没有关系。 (请参阅getAppUserDataDirectory。)

System.Directory中还有其他有用的目录和方便的文件系统实用程序。从某种意义上讲,它是跨平台的,它知道应该根据您的操作系统将内容放到哪里。

理由:如果将工作数据与可执行文件存储在同一目录中,则只有该目录中具有写许可权的人才能正确运行您的程序。只有超级用户可以在/usr/local/bin之类的目录中写入,只有管理员可以在C:\Program Files\的目录中写入。使用用户应用程序目录,任何人都可以运行该应用程序,因为应用程序数据目录是特定于用户的,并且可由他们写,因此这是一个好习惯。

个人而言,我不喜欢应用程序使用配置数据来弄乱我的主要用户区域,但是do想要应用程序,因此建议我的用户区域作为保存我自己的某些内容(getHomeDirectory)的第一个猜测。我建议用户应用程序数据目录,因为您建议了可执行文件的目录,所以听起来像是配置数据。


8
投票

正确的方法是在file.txt文件的data-files字段中列出.cabal,然后使用getDataFileName进行检索。有关前缀独立性,请参见cabal documentation


4
投票

功能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 ()
© www.soinside.com 2019 - 2024. All rights reserved.