Как определить каталог, в котором находится запущенный скрипт или приложение Haskell?

У меня есть сценарий Haskell, который запускается через строку shebang с использованием утилиты runhaskell. Например...

#! /usr/bin/env runhaskell
module Main where
main = do { ... }

Теперь я хотел бы иметь возможность определять каталог, в котором находится этот скрипт, из самого скрипта. Таким образом, если скрипт находится в каталоге /home/me/my-haskell-app/script.hs, я должен иметь возможность запускать его откуда угодно, используя относительный или абсолютный путь, и он должен знать, что находится в каталоге /home/me/my-haskell-app/.

Я думал, что функциональность, доступная в модуле System.Environment, могла бы помочь, но этого не хватило. getProgName, похоже, не предоставил полезную информацию о пути к файлу. Я обнаружил, что переменная окружения _ (символ подчеркивания) иногда будет содержать путь к скрипту при его вызове; однако, как только сценарий вызывается через какую-либо другую программу или родительский сценарий, эта переменная среды, похоже, теряет свое значение (и мне нужно вызвать свой сценарий Haskell из другого родительского приложения).

Также полезно знать, могу ли я определить каталог, в котором находится предварительно скомпилированный исполняемый файл Haskell, используя ту же технику или иначе.


person Chris W.    schedule 26.07.2010    source источник


Ответы (5)


Существует пакет FindBin, который подходит для ваших нужд, а также работает для скомпилированных программ.

person Daniel    schedule 26.07.2010

Насколько я понимаю, это исторически сложно в *nix. Существуют библиотеки для некоторых языков, обеспечивающие такое поведение, в том числе FindBin для Haskell:

http://hackage.haskell.org/package/FindBin

Я не уверен, что это сообщит со сценарием. Вероятно, расположение двоичного файла, который runhaskell скомпилировал непосредственно перед его выполнением.

Кроме того, для скомпилированных проектов Haskell система сборки Cabal предоставляет каталог данных и файлы данных, а также соответствующие сгенерированные Paths_<yourproject>.hs для поиска установленных файлов для вашего проекта во время выполнения.

http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#paths-module

person dino    schedule 26.07.2010
comment
Пакет FindBin, кажется, хорошо работает и для скриптов на основе runhaskell. - person Chris W.; 27.07.2010

Для скомпилированных исполняемых файлов в GHC 7.6 или более поздних версиях вы можете использовать System.Environment.getExecutablePath.

getExecutablePath :: IO FilePathSource

  Returns the absolute pathname of the current executable.
  Note that for scripts and interactive sessions, this is the path to the
  interpreter (e.g. ghci.) 
person cheecheeo    schedule 18.05.2013

Существует executable-path, который работал с моим runghc скриптом. FindBin у меня не работал, так как возвращал мой текущий каталог вместо каталога сценария.

person 4e6    schedule 27.08.2018

Я не смог найти способ определить путь к скрипту из Haskell (очень жаль, ИМХО). Однако в качестве обходного пути вы можете обернуть свой сценарий Haskell внутри сценария оболочки:

#!/bin/sh

SCRIPT_DIR=`dirname $0`

runhaskell <<EOF
main = putStrLn "My script is in \"$SCRIPT_DIR\""
EOF
person devmusings    schedule 16.09.2010