uncompress.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "io"
  6. "os"
  7. "strings"
  8. "github.com/schollz/progressbar"
  9. "github.com/pierrec/cmdflag"
  10. "github.com/pierrec/lz4"
  11. )
  12. // Uncompress uncompresses a set of files or from stdin to stdout.
  13. func Uncompress(_ *flag.FlagSet) cmdflag.Handler {
  14. return func(args ...string) (int, error) {
  15. zr := lz4.NewReader(nil)
  16. // Use stdin/stdout if no file provided.
  17. if len(args) == 0 {
  18. zr.Reset(os.Stdin)
  19. _, err := io.Copy(os.Stdout, zr)
  20. return 0, err
  21. }
  22. for fidx, zfilename := range args {
  23. // Input file.
  24. zfile, err := os.Open(zfilename)
  25. if err != nil {
  26. return fidx, err
  27. }
  28. zinfo, err := zfile.Stat()
  29. if err != nil {
  30. return fidx, err
  31. }
  32. mode := zinfo.Mode() // use the same mode for the output file
  33. // Output file.
  34. filename := strings.TrimSuffix(zfilename, lz4.Extension)
  35. file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, mode)
  36. if err != nil {
  37. return fidx, err
  38. }
  39. zr.Reset(zfile)
  40. zfinfo, err := zfile.Stat()
  41. if err != nil {
  42. return fidx, err
  43. }
  44. var (
  45. size int
  46. out io.Writer = file
  47. zsize = zfinfo.Size()
  48. bar *progressbar.ProgressBar
  49. )
  50. if zsize > 0 {
  51. bar = progressbar.NewOptions64(zsize,
  52. // File transfers are usually slow, make sure we display the bar at 0%.
  53. progressbar.OptionSetRenderBlankState(true),
  54. // Display the filename.
  55. progressbar.OptionSetDescription(filename),
  56. progressbar.OptionClearOnFinish(),
  57. )
  58. out = io.MultiWriter(out, bar)
  59. zr.OnBlockDone = func(n int) {
  60. size += n
  61. }
  62. }
  63. // Uncompress.
  64. _, err = io.Copy(out, zr)
  65. if err != nil {
  66. return fidx, err
  67. }
  68. for _, c := range []io.Closer{zfile, file} {
  69. err := c.Close()
  70. if err != nil {
  71. return fidx, err
  72. }
  73. }
  74. if bar != nil {
  75. _ = bar.Clear()
  76. fmt.Printf("%s %d\n", zfilename, size)
  77. }
  78. }
  79. return len(args), nil
  80. }
  81. }