-
Notifications
You must be signed in to change notification settings - Fork 0
/
concat.go
122 lines (96 loc) · 2.18 KB
/
concat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"bufio"
"errors"
"flag"
"fmt"
"os"
"strings"
)
const newline = "\n"
type config struct {
inFilesRaw,
outFile string
inFiles []string
}
var cfg = config{
inFilesRaw: "",
outFile: "",
inFiles: []string{},
}
func init() {
flag.StringVar(&cfg.inFilesRaw, "in", cfg.inFilesRaw, "CSV file paths to be combined, paths separated by a space")
flag.StringVar(&cfg.outFile, "out", cfg.outFile, "Combined output file path, will overwrite output location")
}
func main() {
flag.Parse()
parseInFiles()
first := firstInFile(cfg.inFiles)
copyToOutput(first, cfg.outFile, true)
latter := latterInFiles(cfg.inFiles)
for _, f := range latter {
copyToOutput(f, cfg.outFile, false)
}
fmt.Println("Success: CSV Concat completed.")
}
// parseInFiles splits the inFilesRaw into inFiles based on spaces
func parseInFiles() {
if cfg.inFilesRaw == "" {
err := errors.New("Error: no input files")
abort(err)
}
cfg.inFiles = strings.Split(cfg.inFilesRaw, " ")
}
// firstInFile returns the first file in cfg.inFiles
func firstInFile(files []string) string {
if len(files) > 0 {
return files[0]
}
return ""
}
// latterInFiles returns all except for the first file in cfg.inFiles
func latterInFiles(files []string) []string {
if len(files) > 1 {
return files[1:]
}
return []string{}
}
// copyToOutput copies the source CSV to the target CSV destination by appending to the target file,
// takes into account if it should copy the header (first) row as well
func copyToOutput(source, target string, copyHeader bool) error {
fOut, err := os.OpenFile(target, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer fOut.Close()
fIn, err := os.Open(source)
if err != nil {
return err
}
defer fIn.Close()
firstRow := true
scanner := bufio.NewScanner(fIn)
for scanner.Scan() {
append := true
if firstRow {
if !copyHeader {
append = false
}
firstRow = false
}
if append {
if _, err = fOut.WriteString(scanner.Text() + newline); err != nil {
return err
}
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
// abort outputs error & exits
func abort(e error) {
fmt.Println(e)
os.Exit(255)
}