如何压缩Elixir中的目录?

时间:2014-03-21 07:55:58

标签: elixir

我知道如何在Elixir中以写入模式打开一个zip文件:

file = File.open("myzip.zip", [:write, :compressed])

但在此之后,如果我有一个目录/home/lowks/big_files,我该如何将其写入file

2 个答案:

答案 0 :(得分:9)

如果您使用的是zip文件,则需要使用:zip.extract('foo.zip'):zip.create(name, [{'foo', file1data}, file2path, ...])

:zip.create采用名称和列表,其中包含两个选项之一:

  1. 包含文件名的元组和要压缩的二进制数据。
  2. 要压缩文件的路径。
  3. :zip.extract可以获取文件的路径,也可以使用代表zip存档的二进制数据(可能来自zip上的File.open)。

    您可以执行以下操作来获取路径中的文件列表并将其压缩:

    files = File.ls!(path)
            |> Enum.map(fn filename -> Path.join(path, filename) end)
            |> Enum.map(&String.to_char_list!/1)
    
    :zip.create('foo.zip', files)
    

答案 1 :(得分:0)

这是一个相当不错的答案,但这里有一个更好的答案,它支持从一个位置递归地向zip添加目录。

  files = create_files_list(path)
  :zip.create(to_charlist(zip_file_path), files)

这是create_files_list:

  defp create_files_list(path) do
    create_files_list(File.ls!(path), path)
  end
  defp create_files_list(paths, path) do
    create_files_list(paths, path, path)
  end
  defp create_files_list(paths, path, base_path) do
    Enum.reduce(paths, [],
      fn(filename, acc) ->
        filename_path = Path.join(path, filename)
        if File.dir?(filename_path) do
          acc ++ create_files_list(File.ls!(filename_path), filename_path, base_path)
        else
          filenm = 
            if base_path, 
              do: String.replace_leading(filename_path, base_path, ""), 
              else: filename_path
          [{String.to_char_list(filenm), File.read!(filename_path)} | acc]
        end
      end
    )
  end

一句警告;我没有将它用于任何非常大的东西,它可能会在这里使用File.read来破坏一切。我不确定如何使用文件句柄,但我认为这是可能的。随意改进和贡献; - )

我也会缓存zip文件,因此每次都不会执行。