Is it possible to extract a tar.xz package in golang? My understanding is it's possible to use the library for tar and sending it to an xz go library.
Asked
Active
Viewed 5,295 times
3 Answers
6
I recently created an XZ decompression package so it is now possible to extract a tar.xz using only Go code.
The following code extracts the file myfile.tar.xz
to the current
directory:
package main
import (
"archive/tar"
"fmt"
"io"
"log"
"os"
"github.com/xi2/xz"
)
func main() {
// Open a file
f, err := os.Open("myfile.tar.xz")
if err != nil {
log.Fatal(err)
}
// Create an xz Reader
r, err := xz.NewReader(f, 0)
if err != nil {
log.Fatal(err)
}
// Create a tar Reader
tr := tar.NewReader(r)
// Iterate through the files in the archive.
for {
hdr, err := tr.Next()
if err == io.EOF {
// end of tar archive
break
}
if err != nil {
log.Fatal(err)
}
switch hdr.Typeflag {
case tar.TypeDir:
// create a directory
fmt.Println("creating: " + hdr.Name)
err = os.MkdirAll(hdr.Name, 0777)
if err != nil {
log.Fatal(err)
}
case tar.TypeReg, tar.TypeRegA:
// write a file
fmt.Println("extracting: " + hdr.Name)
w, err := os.Create(hdr.Name)
if err != nil {
log.Fatal(err)
}
_, err = io.Copy(w, tr)
if err != nil {
log.Fatal(err)
}
w.Close()
}
}
f.Close()
}

Michael Hampton
- 9,737
- 4
- 55
- 96

xi2
- 96
- 1
- 2
4
http://golang.org/pkg/archive/tar/#example_
also you can do
import "os/exec"
cmd := exec.Command("tar", "-x", "/your/archive.tar.xz")
err := cmd.Run()

Uvelichitel
- 8,220
- 1
- 19
- 36
-
This doesn't actually decompress via tar. You probably want tar xvJf archive.tar.xz... – Fire Feb 01 '15 at 07:08
-
@Fire It does with GNU tar, as GNU tar automatically detects the presence of compression. None the less, to keep this program compatible with other tar implementations that do not provide `J`, you might want to set up a pipe between `xz -d` and `tar x`. Also, why do you provide `v`? It isn't required. – fuz Feb 02 '15 at 07:30
-
1That's true. `v` isn't required. – Fire Feb 02 '15 at 17:00
1
There is no Lempel-Ziv-Markow encoder or decoder in the Go standard library. If you are allowed to assume that the platform your code runs on provides the xz
utility, you could use stub functions like these:
import "os/exec"
// decompress xz compressed data stream r.
func UnxzReader(r io.Reader) (io.ReadCloser, error) {
unxz := exec.Command("xz", "-d")
unxz.Stdin = r
out, err := unxz.StdoutPipe()
if err != nil {
return nil, err
}
err = unxz.Start()
if err != nil {
return nil, err
}
// we are not interested in the exit status, but we should really collect
// that zombie process
go unxz.Wait()
return out, nil
}

fuz
- 88,405
- 25
- 200
- 352
-
-
-
I have code that processes the tar, but it is also http://golang.org/pkg/archive/tar/#example here. It would be best for completeness to have code that starts from an os.Open() and decompresses xz using the above code. Afterwards, send it to tar and for each directory / file extract. – Fire Feb 02 '15 at 16:48
-
-
@Fire The rest is left as an exercise to the reader. It's not really difficult. – fuz Feb 02 '15 at 17:16
-
For future readers, note that `xz -d -T0` uses all the threads of the computer to decompress. – Fire Feb 02 '15 at 22:53