Skip to content

Instantly share code, notes, and snippets.

@paulerickson
Last active February 25, 2024 13:23
Show Gist options
  • Save paulerickson/6d8650947ee4e3f3dbcc28fde10eaae7 to your computer and use it in GitHub Desktop.
Save paulerickson/6d8650947ee4e3f3dbcc28fde10eaae7 to your computer and use it in GitHub Desktop.
Golang unzip implementation
package unzip
import "archive/zip"
/**
* Extract a zip file named source to directory destination. Handles cases where destination dir…
* - does not exist (creates it)
* - is empty
* - already has source archive extracted into it (files are overwritten)
* - has other files in it, not in source archive (not overwritten)
* But is expected to fail if it…
* - is not writable
* - contains a non-empty directory with the same path as a file in source archive (that's not a simple overwrite)
*/
func Unzip(source, destination string) error {
archive, err := zip.OpenReader(source)
if err != nil {
return err
}
defer archive.Close()
for _, file := range archive.Reader.File {
reader, err := file.Open()
if err != nil {
return err
}
defer reader.Close()
path := filepath.Join(destination, file.Name)
// Remove file if it already exists; no problem if it doesn't; other cases can error out below
_ = os.Remove(path)
// Create a directory at path, including parents
err = os.MkdirAll(path, os.ModePerm)
if err != nil {
return err
}
// If file is _supposed_ to be a directory, we're done
if file.FileInfo().IsDir() {
continue
}
// otherwise, remove that directory (_not_ including parents)
err = os.Remove(path)
if err != nil {
return err
}
// and create the actual file. This ensures that the parent directories exist!
// An archive may have a single file with a nested path, rather than a file for each parent dir
writer, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
if err != nil {
return err
}
defer writer.Close()
_, err = io.Copy(writer, reader)
if err != nil {
return err
}
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment