Go playground にも書いたけど、動かない 対象となるファイルが多すぎたか

package main

import (
    "archive/zip"
    "fmt"
    "io"
    "io/ioutil"
    "os"
    "path/filepath"
)

func main() {
    filePaths, _ := find(".")
    zipPath := "/tmp/test.zip"
    if err := archive(zipPath, filePaths); err != nil {
    panic(err)
    }
}

// find
func find(targetDir string) ([]string, error) {

    var paths []string
    err := filepath.Walk(targetDir,
        func(path string, info os.FileInfo, err error) error {
            rel, err := filepath.Rel(targetDir, path)
            if err != nil {
                return err
            }

            if info.IsDir() {
                paths = append(paths, fmt.Sprintf("%s/", rel))
                return nil
            }

            paths = append(paths, rel)

            return nil
        })

    if err != nil {
        return nil, err
    }

    return paths, nil
}

func archive(output string, paths []string) error {
    var compressedFile *os.File
    var err error

    //ZIPファイル作成
    if compressedFile, err = os.Create(output); err != nil {
        return err
    }
    defer compressedFile.Close()

    if err := compress(compressedFile, ".", paths); err != nil {
        return err
    }

    return nil
}

func compress(compressedFile io.Writer, targetDir string, files []string) error {
    w := zip.NewWriter(compressedFile)

    for _, filename := range files {
        filepath := fmt.Sprintf("%s/%s", targetDir, filename)
        info, err := os.Stat(filepath)
        if err != nil {
            return err
        }

        if info.IsDir() {
            continue
        }

        file, err := os.Open(filepath)
        if err != nil {
            return err
        }
        defer file.Close()

        hdr, err := zip.FileInfoHeader(info)
        if err != nil {
            return err
        }

        hdr.Name = filename

        f, err := w.CreateHeader(hdr)
        if err != nil {
            return err
        }

        contents, _ := ioutil.ReadFile(filepath)
        _, err = f.Write(contents)
        if err != nil {
            return err
        }
    }

    if err := w.Close(); err != nil {
        return err
    }

    return nil
}

全体像としてはこんな感じで、特に重要なのはこのあたり

hdr, err := zip.FileInfoHeader(info)
        if err != nil {
            return err
        }

        hdr.Name = filename

よくあるCreateしてio.WriterにWriteするだけでもZIPは作れるし、問題なく展開できるけど
タイムスタンプがめっちゃカコになる だから、対象のファイル情報をコピーする感じ

割とハマったけど、これで問題なく進めれる!!

今作ってるもの

Golang製のディレクトリバックアップツールを作った話 に書いた standというバックアップツールで、ハマった場所