haskell: cd 命令在 shake/command 库中不起作用
haskell: cd command does not work in shake/command library
出于某种原因,我无法使 cd
命令在 shake/command
Haskell 库中工作。它认为我用 cd
调用的目录不存在,即使它存在于文件系统中。
这是我的代码的摘录:
dataDir = "data"
data Settings = Settings {
url :: String
} deriving (Eq, Show, Generic, JSON.ToJSON, JSON.FromJSON)
settings :: String -> Handler Settings
settings subfolder = let
gitPath = dataDir ++ "/" ++ subfolder ++ "/git/.git"
in do
pathExists <- liftIO $ doesPathExist gitPath
-- Stdout pwdOut <- liftIO $ cmd ("pwd" :: String)
-- liftIO $ putStrLn $ pwdOut
if not pathExists
then do
liftIO $ (cmd_ ("mkdir -p" :: String) [gitPath] :: IO ())
liftIO $ (cmd_ ("cd" :: String) [gitPath] :: IO ())
liftIO $ (cmd_ ("git init" :: String) :: IO ())
return $ Settings { url = ""}
else do
liftIO $ (cmd_ (Cwd ".") ("cd" :: String) [gitPath] :: IO ())
Stdout out <- liftIO $ (cmd ("git config --get remote.origin.url" :: String))
return $ Settings {url = out}
在两种情况下都失败并出现错误 cd: createProcess: runInteractiveProcess: exec: does not exist (No such file or directory)
:如果目录存在并且当执行 mkdir
命令时。
无法理解它。但在我向 shake 的 github 页面提交错误之前,我想与您确认我没有做任何可能导致这种行为的愚蠢行为。
在此先感谢您的帮助。
Shake 的 Haddock page describes cmd_
, and links to its source. There we can see that cmd_
eventually calls commandExplicitIO
, which constructs a ProcessOpts
with RawCommand
and passes it to process
. process
then takes that ProcessOpts
, pattern-matches it as a RawCommand
(via cmdSpec
), and calls proc
. We have now entered the well-documented zone:您必须给 proc
一个 可执行文件 ,而 cd
不是可执行文件。 (为什么?由于进程无法更改其父进程的工作目录,因此 cd
必须是 shell 内置。)
如其他答案所述,cd
不是可执行文件,因此如果您想 运行 它,则必须将 Shell
传递给 cmd
.
但是,几乎可以肯定的是,您不想在命令中调用 cd
,因为它 不会 更改任何后续目录命令。每个 cmd
都是一个单独的进程,具有单独的环境,因此后续命令将在一个全新的环境中,并且与 cd
之前的工作目录相同。解决方案是将 (Cwd gitPath)
传递给每个要对给定目录进行操作的命令。
出于某种原因,我无法使 cd
命令在 shake/command
Haskell 库中工作。它认为我用 cd
调用的目录不存在,即使它存在于文件系统中。
这是我的代码的摘录:
dataDir = "data"
data Settings = Settings {
url :: String
} deriving (Eq, Show, Generic, JSON.ToJSON, JSON.FromJSON)
settings :: String -> Handler Settings
settings subfolder = let
gitPath = dataDir ++ "/" ++ subfolder ++ "/git/.git"
in do
pathExists <- liftIO $ doesPathExist gitPath
-- Stdout pwdOut <- liftIO $ cmd ("pwd" :: String)
-- liftIO $ putStrLn $ pwdOut
if not pathExists
then do
liftIO $ (cmd_ ("mkdir -p" :: String) [gitPath] :: IO ())
liftIO $ (cmd_ ("cd" :: String) [gitPath] :: IO ())
liftIO $ (cmd_ ("git init" :: String) :: IO ())
return $ Settings { url = ""}
else do
liftIO $ (cmd_ (Cwd ".") ("cd" :: String) [gitPath] :: IO ())
Stdout out <- liftIO $ (cmd ("git config --get remote.origin.url" :: String))
return $ Settings {url = out}
在两种情况下都失败并出现错误 cd: createProcess: runInteractiveProcess: exec: does not exist (No such file or directory)
:如果目录存在并且当执行 mkdir
命令时。
无法理解它。但在我向 shake 的 github 页面提交错误之前,我想与您确认我没有做任何可能导致这种行为的愚蠢行为。
在此先感谢您的帮助。
Shake 的 Haddock page describes cmd_
, and links to its source. There we can see that cmd_
eventually calls commandExplicitIO
, which constructs a ProcessOpts
with RawCommand
and passes it to process
. process
then takes that ProcessOpts
, pattern-matches it as a RawCommand
(via cmdSpec
), and calls proc
. We have now entered the well-documented zone:您必须给 proc
一个 可执行文件 ,而 cd
不是可执行文件。 (为什么?由于进程无法更改其父进程的工作目录,因此 cd
必须是 shell 内置。)
如其他答案所述,cd
不是可执行文件,因此如果您想 运行 它,则必须将 Shell
传递给 cmd
.
但是,几乎可以肯定的是,您不想在命令中调用 cd
,因为它 不会 更改任何后续目录命令。每个 cmd
都是一个单独的进程,具有单独的环境,因此后续命令将在一个全新的环境中,并且与 cd
之前的工作目录相同。解决方案是将 (Cwd gitPath)
传递给每个要对给定目录进行操作的命令。