// catn.go
/*
In the following code, panic us used instead of os.Exit to quit the
program. Calling panic ensures deferred functions are called. Calling
os.Exit skips calling deferred functions.
See https://groups.google.com/forum/#!topic/golang-nuts/_Twwb5ULStM for
discussion of how to get both error codes and deferred functions to work
correctly.
*/
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
// Split a file name string like "conf.py" into strings "conf" and "py".
func splitAtLastDot(name string) (string, string) {
dotLoc := strings.LastIndex(name, ".")
if dotLoc == -1 {
return name, ""
}
return name[:dotLoc], name[dotLoc+1:]
}
func main() {
//
// check number of command-line arguments
//
nargs := len(os.Args) // os.Args contains command-line arguments
if nargs != 2 {
fmt.Println("Error: exactly one filename argument must be provided")
panic("exited")
}
inname := os.Args[1]
//
// open the input file
//
infile, err := os.Open(inname)
defer infile.Close() // run this when the function is done
if err != nil {
fmt.Printf("Error: cannot open file \"%s\" (%s)", inname, err)
panic("exited")
}
//
// open the output file
//
n, ext := splitAtLastDot(inname)
outname := n + "-lines." + ext
outfile, err := os.Create(outname) // deletes existing file with same name
defer outfile.Close() // run this when the function is done
if err != nil {
fmt.Printf("Error: cannot create file \"%s\" (%s)", outname, err)
panic("exited")
}
//
// create the writer
//
writer := bufio.NewWriter(outfile)
defer writer.Flush() // run this when the function is done
//
// process the files line by line with a scanner
//
scanner := bufio.NewScanner(infile)
num := 1
for scanner.Scan() {
line := scanner.Text()
// fmt.Printf("%5d %s\n", num, line) // uncomment to print to screen
fmt.Fprintf(writer, "%5d %s\n", num, line)
num++
}
fmt.Println("Results written to " + outname + ".")
}