gopkg.in/hugelgupf/u-root.v7@v7.0.0-20180831062900-6a07824681b2/cmds/sort/sort.go (about) 1 // Copyright 2017 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Sort lines. 6 // 7 // Synopsis: 8 // sort [OPTIONS]... [INPUT]... 9 // 10 // Description: 11 // Sort copies lines from the input to the output, sorting them in the 12 // process. This does nothing fancy (no multi-threading, compression, 13 // optiminzations, ...); it simply uses Go's sort.Sort function. 14 // 15 // Options: 16 // -r: reverse 17 // -o FILE: output file 18 package main 19 20 import ( 21 "flag" 22 "io/ioutil" 23 "log" 24 "os" 25 "sort" 26 "strings" 27 ) 28 29 var ( 30 reverse = flag.Bool("r", false, "Reverse") 31 outputFile = flag.String("o", "", "Output file") 32 ) 33 34 func readInput() string { 35 // Input files 36 from := []*os.File{} 37 if flag.NArg() > 0 { 38 for _, v := range flag.Args() { 39 if f, err := os.Open(v); err == nil { 40 from = append(from, f) 41 defer f.Close() 42 } else { 43 log.Fatal(err) 44 } 45 } 46 } else { 47 from = []*os.File{os.Stdin} 48 } 49 50 // Read unicode string from input 51 fileContents := []string{} 52 for _, f := range from { 53 bytes, err := ioutil.ReadAll(f) 54 if err != nil { 55 log.Fatal(err) 56 } 57 s := string(bytes) 58 fileContents = append(fileContents, s) 59 // Add a separator between files if the file is not newline 60 // terminated. Prevents concatenating lines between files. 61 if len(s) > 0 && s[len(s)-1] != '\n' { 62 fileContents = append(fileContents, "\n") 63 } 64 } 65 return strings.Join(fileContents, "") 66 } 67 68 func sortAlgorithm(s string) string { 69 if len(s) == 0 { 70 return "" // edge case mimics coreutils 71 } 72 if s[len(s)-1] == '\n' { 73 s = s[:len(s)-1] // remove newline terminator 74 } 75 lines := strings.Split(string(s), "\n") 76 if *reverse { 77 sort.Sort(sort.Reverse(sort.StringSlice(lines))) 78 } else { 79 sort.Strings(lines) 80 } 81 return strings.Join(lines, "\n") + "\n" // append newline terminator 82 } 83 84 func writeOutput(s string) { 85 to := os.Stdout 86 if *outputFile != "" { 87 if f, err := os.Create(*outputFile); err == nil { 88 to = f 89 defer f.Close() 90 } else { 91 log.Fatal(err) 92 } 93 } 94 to.Write([]byte(s)) 95 } 96 97 func main() { 98 flag.Parse() 99 100 // Input files must be closed before writing to output files to solve 101 // the situtation in which the output file is the same as an input. 102 writeOutput(sortAlgorithm(readInput())) 103 }