Add 7z support to recursive_decompress.go
[cmccabe-bin] / recursive_decompress.go
1 package main
2
3 import (
4         "flag"
5         "os/exec"
6         "path/filepath"
7         "fmt"
8         "os"
9         "strings"
10 )
11
12 var removeArchives *bool
13
14 func processPath(curPath string) error {
15         info, err := os.Stat(curPath)
16         if err != nil {
17                 return fmt.Errorf("Unable to stat %s: %s", curPath, err.Error())
18         }
19         if info.IsDir() {
20                 entries, err := os.ReadDir(curPath)
21                 if err != nil {
22                         return fmt.Errorf("Unable to call readdir on %s: %s", curPath, err.Error())
23                 }
24                 for i := range(entries) {
25                         err := processPath(filepath.Join(curPath, entries[i].Name()))
26                         if err != nil {
27                                 return err
28                         }
29                 }
30         } else {
31                 extractedBaseName, err := extractIfPossible(curPath)
32                 if err != nil {
33                         return err
34                 }
35                 if extractedBaseName != "" {
36                         err = processPath(filepath.Join(filepath.Dir(curPath), extractedBaseName))
37                         if err != nil {
38                                 return err
39                         }
40                         if *removeArchives {
41                                 err = os.Remove(curPath)
42                                 if err != nil {
43                                         return fmt.Errorf("Unable to remove archive file %s: %s", curPath, err.Error())
44                                 }
45                                 fmt.Printf("== rm %s\n", curPath)
46                         }
47                 }
48         }
49         return nil
50 }
51
52 func extractIfPossible(curPath string) (string, error) {
53         if strings.HasSuffix(curPath, ".tgz") {
54                 return extractTgz(curPath)
55         } else if strings.HasSuffix(curPath, ".7z") {
56                 return extract7z(curPath)
57         }
58         return "", nil
59 }
60
61 func extractTgz(curPath string) (string, error) {
62         fmt.Printf("== decompressing tar file %s\n", curPath)
63         cmd := exec.Command("tar", "xvf", filepath.Base(curPath))
64         cmd.Dir = filepath.Dir(curPath)
65         //cmd.Stdout = os.Stdout
66         err := cmd.Run()
67         if err != nil {
68                 return "", fmt.Errorf("error running tar xvf on %s: %s", curPath, err.Error())
69         }
70         return filepath.Base(curPath[:len(curPath) - len(".tgz")]), nil
71 }
72
73 func extract7z(curPath string) (string, error) {
74         fmt.Printf("== decompressing 7z file %s\n", curPath)
75         extractedBaseName := curPath[:len(curPath) - len(".7z")]
76         err := os.Mkdir(extractedBaseName, 0755)
77         if err != nil {
78                 return "", fmt.Errorf("unable to mkdir '%s': %s", extractedBaseName, err.Error())
79         }
80         absCurPath, err := filepath.Abs(curPath)
81         if err != nil {
82                 return "", fmt.Errorf("unable to get absolute path for '%s': %s", curPath, err.Error())
83         }
84         absExtractedBaseName, err := filepath.Abs(extractedBaseName)
85         if err != nil {
86                 return "", fmt.Errorf("unable to get absolute path for '%s': %s", extractedBaseName, err.Error())
87         }
88         cmd := exec.Command("7z", "x", absCurPath)
89         cmd.Dir = absExtractedBaseName
90         cmd.Stdout = os.Stdout
91         err = cmd.Run()
92         if err != nil {
93                 return "", fmt.Errorf("error running 7z on %s: %s", curPath, err.Error())
94         }
95         return extractedBaseName, nil
96 }
97
98 func main() {
99         removeArchives = flag.Bool("r", false, "Remove archive files after decompressing them")
100         flag.Usage = func() {
101                 fmt.Printf("recursive_decompress: recursively decompresses a path.\n")
102                 fmt.Printf("usage: recursive_decompress [flags] [paths...]\n")
103                 fmt.Printf("\n")
104                 flag.PrintDefaults()
105         }
106         flag.Parse()
107         curPath := "."
108         if flag.Arg(0) != "" {
109                 curPath = flag.Arg(0)
110         }
111         err := processPath(curPath)
112         if err != nil {
113                 fmt.Printf("error: %s\n", err.Error())
114                 os.Exit(1)
115         }
116         os.Exit(0)
117 }