我尝试使用1.60082625657186e-11
在Haskell中自动执行某些文件管理。我的脚本同步工作,但在我的用例中,我有大约20个目录,每个目录我想开始一个长时间运行的进程,所以我也使用System.Directory
,这似乎是造成问题。
最小例子:
Control.Concurrent.Async
预期产出:
#!/usr/bin/env stack
-- stack --resolver lts-10.3 --install-ghc runghc --package async
import Control.Concurrent.Async (Concurrently(..), runConcurrently)
import Control.Monad (filterM)
import System.Directory as Dir
import System.Process (callCommand)
dirs :: IO [FilePath]
dirs = do
prefix <- (++ "/Desktop/dirs/") <$> Dir.getHomeDirectory
paths <- fmap (prefix ++) <$> Dir.listDirectory prefix
filterM Dir.doesDirectoryExist paths
pullDir :: FilePath -> IO ()
pullDir dir = Dir.withCurrentDirectory dir $ callCommand "pwd"
main :: IO ()
main = dirs >>= runConcurrently . traverse (Concurrently . pullDir) >> pure ()
实际输出(变化!):
/Users/daniel/Desktop/dirs/1
/Users/daniel/Desktop/dirs/2
/Users/daniel/Desktop/dirs/3
/Users/daniel/Desktop/dirs/4
/Users/daniel/Desktop/dirs/5
我们看到实际输出多次运行/Users/daniel/Desktop/dirs/3
/Users/daniel/Desktop/dirs/4
/Users/daniel/Desktop/dirs/3
/Users/daniel/Desktop/dirs/5
/Users/daniel/Desktop/dirs/5
同一目录,并且无法为某些目录运行pwd
。我几乎肯定这与pwd
有关。
如何在保留并发性的同时正确实现这一点?
答案 0 :(得分:2)
withCurrentDirectory
无法做到这一点。当前目录是进程范围的设置。每当有什么东西改变它时,它就会改变过程中的一切。这不是Haskell问题 - 它只是“当前目录”的概念是如何工作的。
要使其同时工作,您需要使用完整路径来代替所有内容,而不是更改当前目录。