Linux 该目录被删除得太早

Linux 该目录被删除得太早,linux,haskell,directory,lazy-evaluation,tar,Linux,Haskell,Directory,Lazy Evaluation,Tar,我正在尝试使用Codec.Archive.tar从目录的内容创建一个tar文件,但我还想在创建tar文件后清理目录。下面是一个小例子,说明了我的问题: import System.Directory import qualified Codec.Archive.Tar as T listFile = do createDirectory "dir" createDirectory "dir/dir2" tarfile <- fmap

我正在尝试使用
Codec.Archive.tar
从目录的内容创建一个tar文件,但我还想在创建tar文件后清理目录。下面是一个小例子,说明了我的问题:

import System.Directory
import qualified Codec.Archive.Tar as T

listFile = do createDirectory "dir"
              createDirectory "dir/dir2"
              tarfile <- fmap T.write $ T.pack "dir" ["dir2"]
              removeDirectoryRecursive "dir"
              return tarfile
我猜这是因为tar文件被延迟生成,而目录被严格清理。因此,在实际创建tar文件之前删除目录


首先,我对失败原因的分析正确吗?如果是,我能做些什么来解决这个问题?我不想严格地生成tar文件,因为它可能相当大,而且我不想将其全部存储在内存中。在生成tar文件之前延迟删除目录的“惯用”方法是什么?

最简单的解决方案是反转对
listFile
函数的控制。与其让它返回一个惰性的
ByteString
(一旦删除目录,它将毫无用处),不如让它执行IO操作来使用
ByteString
,并在删除目录之前对其进行处理。例如:

import System.Directory
import qualified Codec.Archive.Tar as T
import qualified Data.ByteString.Lazy as LB
import System.IO

listFileTo :: (LB.ByteString -> IO ()) -> IO ()
listFileTo sink = do createDirectory "dir"
                     createDirectory "dir/dir2"
                     tarfile <- fmap T.write $ T.pack "dir" ["dir2"]
                     sink tarfile
                     removeDirectoryRecursive "dir"

main :: IO ()
main = listFileTo (\tarcontents -> withBinaryFile "my.tar" WriteMode
                    (\h -> LB.hPut h tarcontents))
例如,这将允许您确定生成的tarfile的大小,而无需实际对其进行任何操作,不过您必须注意在
接收器中严格评估结果:

{-# LANGUAGE BangPatterns #-}

main :: IO ()
main = do size <- listFileTo (\tarcontents ->
                                let !size = LB.length tarcontents in return size)
          print size
{-#语言模式}
main::IO()
main=do大小
让我来!大小=磅。长度(返回大小中的内容)
印刷尺寸

“我不想严格地生成tar文件,因为它可能相当大,而且我不想将其全部存储在内存中。”您是否也尝试将tar文件写入磁盘?您可能正在寻找一个合适的流库(管道、管道、流、io流等),可能有人已经在流接口中包装了tar操作。我确实认为这些库中的一个可以解决这个问题,但我需要花一段时间阅读所有文档并了解发生了什么。这有点令人困惑,以前从未在Haskell中处理过流媒体。
listFileTo :: (LB.ByteString -> IO a) -> IO a
listFileTo sink = do createDirectory "dir"
                     createDirectory "dir/dir2"
                     tarfile <- fmap T.write $ T.pack "dir" ["dir2"]
                     result <- sink tarfile
                     removeDirectoryRecursive "dir"
                     return result
{-# LANGUAGE BangPatterns #-}

main :: IO ()
main = do size <- listFileTo (\tarcontents ->
                                let !size = LB.length tarcontents in return size)
          print size