Skip to content

Instantly share code, notes, and snippets.

@iamralch
Last active February 11, 2025 19:32
Show Gist options
  • Select an option

  • Save iamralch/424e6784facc0ba907ae to your computer and use it in GitHub Desktop.

Select an option

Save iamralch/424e6784facc0ba907ae to your computer and use it in GitHub Desktop.
ZIP archives in Golang
import (
"archive/zip"
"io"
"os"
"path/filepath"
"strings"
)
func zipit(source, target string) error {
zipfile, err := os.Create(target)
if err != nil {
return err
}
defer zipfile.Close()
archive := zip.NewWriter(zipfile)
defer archive.Close()
info, err := os.Stat(source)
if err != nil {
return nil
}
var baseDir string
if info.IsDir() {
baseDir = filepath.Base(source)
}
filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
if baseDir != "" {
header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
}
if info.IsDir() {
header.Name += "/"
} else {
header.Method = zip.Deflate
}
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
return err
})
return err
}
import (
"archive/zip"
"io"
"os"
"path/filepath"
"strings"
)
func unzip(archive, target string) error {
reader, err := zip.OpenReader(archive)
if err != nil {
return err
}
if err := os.MkdirAll(target, 0755); err != nil {
return err
}
for _, file := range reader.File {
path := filepath.Join(target, file.Name)
if file.FileInfo().IsDir() {
os.MkdirAll(path, file.Mode())
continue
}
fileReader, err := file.Open()
if err != nil {
return err
}
defer fileReader.Close()
targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
if err != nil {
return err
}
defer targetFile.Close()
if _, err := io.Copy(targetFile, fileReader); err != nil {
return err
}
}
return nil
}
@yhirose

yhirose commented Jan 23, 2016

Copy link
Copy Markdown

@Svett, thanks for the very useful code. I have a question on line 21 in compress.go. Is there any reason to return nil instead of err in this case?

@rande

rande commented Mar 3, 2016

Copy link
Copy Markdown

The extract function will generate too many open file issue as the defer is only called once the function return, here an altered version:

func Unzip(archive, target string) error {
    reader, err := zip.OpenReader(archive)
    if err != nil {
        return err
    }

    if err := os.MkdirAll(target, 0755); err != nil {
        return err
    }

    for _, file := range reader.File {
        path := filepath.Join(target, file.Name)
        if file.FileInfo().IsDir() {
            os.MkdirAll(path, file.Mode())
            continue
        }

        fileReader, err := file.Open()
        if err != nil {

            if fileReader != nil {
                fileReader.Close()
            }

            return err
        }

        targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
        if err != nil {
            fileReader.Close()

            if targetFile != nil {
                targetFile.Close()
            }

            return err
        }

        if _, err := io.Copy(targetFile, fileReader); err != nil {
            fileReader.Close()
            targetFile.Close()

            return err
        }

        fileReader.Close()
        targetFile.Close()
    }

    return nil
}

@dopatraman

Copy link
Copy Markdown

The zipit function throws an error if the .zip file does not already exist. How do i remedy this?

@anismiles

Copy link
Copy Markdown
	// Check file
	if _, err := os.Stat(archive); os.IsNotExist(err) {
		return err
	}

@hrieke

hrieke commented Oct 19, 2017

Copy link
Copy Markdown

License?

@navono

navono commented Aug 28, 2020

Copy link
Copy Markdown

If have a large files in multiple directory, the filepath.Walk would take a long time to process. Any possible to use goroutine to improve performance?

@royalorc

Copy link
Copy Markdown

hi all, if I have some sub directories, in the code previous, it just make directory of sub directories, how can i restore those files in sub directories?

@royalorc

Copy link
Copy Markdown

if r.File[f].FileInfo().IsDir() {
if err := os.MkdirAll(dstpath, os.ModePerm); err != nil {
return nil, err
}
}
in this piece of code, how could i copy those files which are in this directory?

@iamralch

Copy link
Copy Markdown
Author

You have to walk through the directories until you reach a regular file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment