package main import ( "compress/gzip" "fmt" "io" "math/rand" "os" "path/filepath" "time" "github.com/urfave/cli" ) func main() { app := cli.NewApp() app.Name = "gogzip" app.Description = "golang `compress/gzip` cli, in likeness to GNU gzip" app.Version = "0.1" app.Flags = []cli.Flag{ cli.BoolFlag{ Name: "a,ascii", Usage: "(noop here for compatibility)", }, cli.BoolFlag{ Name: "c,stdout,to-stdout", Usage: "write output to stdout", }, cli.BoolFlag{ Name: "d", Usage: "decompress", }, cli.BoolFlag{ Name: "f,force", Usage: "force", }, cli.BoolFlag{ Name: "k,keep", Usage: "keep original file when compressing", }, cli.BoolFlag{ Name: "l,list", Usage: "for each compressed file, list the size tables", }, cli.BoolFlag{ Name: "L,license", Usage: "license", }, cli.BoolFlag{ Name: "N,name", Usage: "license", }, cli.BoolFlag{ Name: "q,quiet", Usage: "suppress warnings", }, cli.BoolFlag{ Name: "r,recursive", Usage: "if any of the file arguments are directories, recurse them", }, cli.StringFlag{ Name: "S,suffix", Value: ".gz", Usage: "when compressing use suffix value instead of default", }, cli.BoolFlag{ Name: "synchronous", Usage: "sync", }, cli.BoolFlag{ Name: "#,best,fast", Usage: "compression level", }, cli.BoolFlag{ Name: "rsyncable", Usage: "rsyncable", }, cli.VersionFlag, } app.Action = defaultAction app.Run(os.Args) } func defaultAction(c *cli.Context) error { // TODO check whether stdin or its a pty terminal, if no args if c.Bool("decompress") { if c.NArg() == 0 { grdr, err := gzip.NewReader(os.Stdin) if err != nil { return cli.NewExitError(err, 2) } defer grdr.Close() if _, err = io.Copy(os.Stdout, grdr); err != nil { return cli.NewExitError(err, 2) } return nil } for _, arg := range c.Args() { err := func() error { fh, err := os.OpenFile(arg, os.O_RDONLY, 0600) if err != nil { return err } defer fh.Close() fi, err := fh.Stat() if err != nil { return err } newName := gzBasename(c, arg) newFh, err := os.OpenFile(newName, os.O_CREATE|os.O_WRONLY, fi.Mode()) if err != nil { return err } defer newFh.Close() if _, err := io.Copy(newFh, fh); err != nil { return err } return nil }() if err != nil { return cli.NewExitError(err, 2) } } return nil } return nil } func gzBasename(c *cli.Context, s string) string { if filepath.Ext(s) == c.String("suffix") { return filepath.Base(s) } return fmt.Sprint("%s.%d", s, rand.New(rand.NewSource(time.Now().UnixNano())).Intn(100)) }