Reputation: 8533
I know how to open up a zip file in write mode in Elixir:
file = File.open("myzip.zip", [:write, :compressed])
but after this, say if I have a directory /home/lowks/big_files
, how do I write this into file
?
Upvotes: 6
Views: 3352
Reputation: 453
This is a fairly good answer, but here is a better one that supports recursively adding directories to the zip from a location.
files = create_files_list(path)
:zip.create(to_charlist(zip_file_path), files)
And here is 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
A word of warning; I'm not using this for anything very large, it might break everything by using File.read here. I'm not sure how to use File handles but I think it's possible. Feel free to improve and contribute back ;-)
I also cache the zip file so it isn't executed every time.
Upvotes: 2
Reputation: 9261
If you are operating on zip files, you'll need to use :zip.extract('foo.zip')
, and :zip.create(name, [{'foo', file1data}, file2path, ...])
.
:zip.create
takes a name, and a list which can contain either of two options:
:zip.extract
can either take a path to a file, or binary data representing the zip archive (perhaps from doing File.open
on a zip).
You can do something like the following to take a list of files in a path and zip them up:
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)
Upvotes: 10