gpt4 book ai didi

linux - 目录被过早删除

转载 作者:太空狗 更新时间:2023-10-29 12:25:04 26 4
gpt4 key购买 nike

我正在尝试使用 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

当我调用函数 listFile 时,例如从 ghci 中,我回来了

"*** Exception: dir/dir2: getModificationTime:getFileTimes:getFileStatus: does not exist (No such file or directory)

我猜这是由于延迟生成 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))

这里,listFileTo 接受一个“sink”,一个接受惰性 ByteString 并用它执行 IO 操作的函数。例如,上述版本的 main 将其写入 tarfile。

您还可以将其概括为可以从接收器返回值的东西:

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

例如,这将允许您确定生成的 tarfile 的大小而无需实际对其进行任何操作,尽管您必须注意严格评估 sink 中的结果:

{-# LANGUAGE BangPatterns #-}

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

关于linux - 目录被过早删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44317767/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com