Skip to content

Latest commit

 

History

History
90 lines (79 loc) · 3.24 KB

File metadata and controls

90 lines (79 loc) · 3.24 KB

Zip compress and extract

Go Reference

This module provides zip utility functions including scanning central directory for file headers, compress a file or a directory (recursively, with or without root dir unwrapping), decompress/extract all files from a ZIP archive, etc.

package main

import (
	"context"
	"os"

	"github.com/nguyengg/xy3/zipper"
)

func main() {
	// to compress directory "path/to/dir", I must first create the archive file and open for writing.
	archive, _ := os.CreateTemp("", "*.zip")
	defer os.Remove(archive.Name())

	_ = zipper.CompressDir(context.TODO(), "path/to/dir", archive, func(options *zipper.CompressDirOptions) {
		zipper.WithBestCompression(&options.CompressOptions)

		// If "path/to/dir" looks like this:
		//	path/to/dir/test/a.txt
		//	path/to/dir/test/path/b.txt
		//	path/to/dir/test/another/path/c.txt
		//
		// With UnwrapRoot=false (default), archive.zip looks like this:
		//	test/a.txt
		//	test/path/b.txt
		//	test/another/path/c.txt
		//
		// With UnwrapRoot=true (default), archive.zip looks like this:
		//	a.txt
		//	path/b.txt
		//	another/path/c.txt
		//
		// If I'm using xy3 to both compress and extract, generally it's safe to turn UnwrapRoot on because
		// extract will automatically unwrap root for me.
		options.UnwrapRoot = true
	})
	_ = archive.Close()

	// this is how I'd extract the archive in full.
	// the method returns the actual output directory that was created/used so that if there was an error, I can
	// delete output directory to clean up artifacts.
	dir, _ := zipper.Extract(context.TODO(), archive.Name(), ".", func(options *zipper.ExtractOptions) {
		// Generally I want to leave this false so that Extract will create a new directory for me to prevent
		// conflicts. Extract will use the name of the archive ("archive.zip") to create directory such as
		// archive, archive-1, archive-2, etc.
		//
		// If I don't want Extract to create a new directory, pass false here in which case the dir argument
		// must point to a valid directory (Extract can take care of creating this directory for me as well).
		options.UseGivenDirectory = false

		// It is best to leave this setting off (default) as well. The setting is applicable only if the archive
		// actually has a single common root directory like:
		//	test/a.txt
		//	test/path/b.txt
		//	test/another/path/c.txt
		//
		// If that's the case, the output directory would look like this with NoUnwrapRoot=false:
		//	./archive/a.txt
		//	./archive/path/b.txt
		//	./archive/another/path/c.txt
		//
		// If "./archive" already exists, Extract would have used "./archive-1", "./archive-2", etc.
		//
		// If I pass NoUnwrapRoot=true, the output directory would look like this:
		//	./archive/test/a.txt
		//	./archive/test/path/b.txt
		//	./archive/test/another/path/c.txt
		//
		// If I pass both NoUnwrapRoot=true and UseGivenDirectory=true, the output directory would look like:
		//	./test/a.txt
		//	./test/path/b.txt
		//	./test/another/path/c.txt
		//
		// And finally, if I pass NoUnwrapRoot=false and UseGivenDirectory=true, the output directory becomes:
		//	./a.txt
		//	./path/b.txt
		//	./another/path/c.txt
		options.NoUnwrapRoot = false
	})
}