2012-11-28 39 views
7

Tôi muốn viết một công cụ tar_gz trong Go. Đầu vào là giống như lệnh linux:làm thế nào để viết một thư mục [không chỉ các tập tin trong nó] vào một tập tin tar.gz trong golang

$tar czvf targetFileName inputDirectoryPath 

Giả sử tôi đã một inputDirectory có cấu trúc như sau:

test [dir] 
-- 0.txt 
    -- 1 [sub dir] 
     -- 1.txt 

Ví dụ: sử dụng lệnh:

$tar czvf test.tar.gz test/ 

chúng ta có thể tar và gzip sự toàn bộ thư mục kiểm tra.


Vấn đề của tôi là tôi có thể viết một tuyến đường tar và gz để đệ quy lặp lại tất cả tệp trong thư mục kiểm tra và ghi tệp đó vào tệp test.tar.gz. Nhưng tôi không biết cách viết một thư mục vào test.tar.gz. Sau khi chạy chương trình của tôi, cấu trúc trong test.tar.gz tập tin là:

0.txt 
1.txt 

bất cứ ai có thể cho tôi biết làm thế nào để viết thư mục đệ quy đến tập tin đầu ra tar.gz. Cảm ơn rất nhiều.

package main 

    import (
     "fmt" 
     "os" 
     "io" 
     "log" 
     "strings" 
     "archive/tar" 
     "compress/gzip" 
    ) 

    func handleError(_e error) { 
     if _e != nil { 
     log.Fatal(_e) 
     } 
    } 

    func TarGzWrite(_path string, tw *tar.Writer, fi os.FileInfo) { 
     fr, err := os.Open(_path) 
     handleError(err) 
     defer fr.Close() 

     h := new(tar.Header) 
     h.Name = fi.Name() 
     h.Size = fi.Size() 
     h.Mode = int64(fi.Mode()) 
     h.ModTime = fi.ModTime() 

     err = tw.WriteHeader(h) 
     handleError(err) 

     _, err = io.Copy(tw, fr) 
     handleError(err) 
    } 

    func IterDirectory(dirPath string, tw *tar.Writer) { 
     dir, err := os.Open(dirPath) 
     handleError(err) 
     defer dir.Close() 
     fis, err := dir.Readdir(0) 
     handleError(err) 
     for _, fi := range fis { 
     curPath := dirPath + "/" + fi.Name() 
     if fi.IsDir() { 
      //TarGzWrite(curPath, tw, fi) 
      IterDirectory(curPath, tw) 
     } else { 
      fmt.Printf("adding... %s\n", curPath) 
      TarGzWrite(curPath, tw, fi) 
     } 
     } 
    } 

    func TarGz(outFilePath string, inPath string) { 
     // file write 
     fw, err := os.Create(outFilePath) 
     handleError(err) 
     defer fw.Close() 

     // gzip write 
     gw := gzip.NewWriter(fw) 
     defer gw.Close() 

     // tar write 
     tw := tar.NewWriter(gw) 
     defer tw.Close() 

     IterDirectory(inPath, tw) 

     fmt.Println("tar.gz ok") 
    } 

    func main() { 
     targetFilePath := "test.tar.gz" 
     inputDirPath := "test/" 
     TarGz(targetFilePath, strings.TrimRight(inputDirPath, "/")) 
     fmt.Println("Hello, World") 
    } 

Trả lời

10

Bạn chỉ thêm tên tệp vào tar chứ không phải toàn bộ đường dẫn. Bạn cần phải giữ cho toàn bộ con đường cho Tar để có thể hiểu được các thư mục. Bạn chỉ cần thay đổi một dòng:

h.Name = fi.Name() 

nên là:

h.Name = _path 

Trên Linux, đầu ra của tar -tvf test.tar.gz:

-rw-rw-r-- 0/0    0 2012-11-28 11:17 test/0.txt 
-rw-rw-r-- 0/0    0 2012-11-28 11:17 test/sub/1.txt 
+0

Hơn ks rất nhiều. Nó hoạt động. – MadCrazy

4

Một cách khác là sử dụng được xây dựng trong filepath. Chức năng đi bộ

// root_directory has been set further up 

walkFn := func(path string, info os.FileInfo, err error) error { 
    if info.Mode().IsDir() { 
     return nil 
    } 
    // Because of scoping we can reference the external root_directory variable 
    new_path := path[len(root_directory):] 
    if len(new_path) == 0 { 
     return nil 
    } 
    fr, err := os.Open(path) 
    if err != nil { 
     return err 
    } 
    defer fr.Close() 

    if h, err := tar.FileInfoHeader(info, new_path); err != nil { 
     log.Fatalln(err) 
    } else { 
     h.Name = new_path 
     if err = tw.WriteHeader(h); err != nil { 
      log.Fatalln(err) 
     } 
    } 
    if length, err := io.Copy(tw, fr); err != nil { 
     log.Fatalln(err) 
    } else { 
     fmt.Println(length) 
    } 
    return nil 
} 

if err = filepath.Walk(root_directory, walkFn); err != nil { 
    return err 
} 
+1

Tôi nghĩ rằng 'new_path: = path [len (root_directory) +1:]' là tốt hơn để tránh/từ tiền tố của mỗi tập tin. – DarKnight

Các vấn đề liên quan