Skip to content

Instantly share code, notes, and snippets.

@miku
Forked from kylelemons/piping.go
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miku/947916277f261c499628 to your computer and use it in GitHub Desktop.
Save miku/947916277f261c499628 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"exec"
"log"
"os"
)
// Pipeline strings together the given exec.Cmd commands in a similar fashion
// to the Unix pipeline. Each command's standard output is connected to the
// standard input of the next command, and the output of the final command in
// the pipeline is returned, along with the collected standard error of all
// commands and the first error found (if any).
//
// To provide input to the pipeline, assign an io.Reader to the first's Stdin.
func Pipeline(cmds ...*exec.Cmd) (pipeLineOutput, collectedStandardError []byte, pipeLineError os.Error) {
// Require at least one command
if len(cmds) < 1 {
return nil, nil, nil
}
// Collect the output from the command(s)
var output bytes.Buffer
var stderr bytes.Buffer
last := len(cmds) - 1
for i, cmd := range cmds[:last] {
var err os.Error
// Connect each command's stdin to the previous command's stdout
if cmds[i+1].Stdin, err = cmd.StdoutPipe(); err != nil {
return nil, nil, err
}
// Connect each command's stderr to a buffer
cmd.Stderr = &stderr
}
// Connect the output and error for the last command
cmds[last].Stdout, cmds[last].Stderr = &output, &stderr
// Start each command
for _, cmd := range cmds {
if err := cmd.Start(); err != nil {
return output.Bytes(), stderr.Bytes(), err
}
}
// Wait for each command to complete
for _, cmd := range cmds {
if err := cmd.Wait(); err != nil {
return output.Bytes(), stderr.Bytes(), err
}
}
// Return the pipeline output and the collected standard error
return output.Bytes(), stderr.Bytes(), nil
}
func main() {
// Collect directories from the command-line
var dirs []string
if len(os.Args) > 1 {
dirs = os.Args[1:]
} else {
dirs = []string{"."}
}
// Run the command on each directory
for _, dir := range dirs {
// find $DIR -type f # Find all files
ls := exec.Command("find", dir, "-type", "f")
// | grep -v '/[._]' # Ignore hidden/temporary files
visible := exec.Command("egrep", "-v", `/[._]`)
// | sort -t. -k2 # Sort by file extension
sort := exec.Command("sort", "-t.", "-k2")
// Run the pipeline
output, stderr, err := Pipeline(ls, visible, sort)
if err != nil {
log.Printf("dir %q: %s", dir, err.String())
}
// Print the stdout, if any
if len(output) > 0 {
log.Printf("%q:\n%s", dir, output)
}
// Print the stderr, if any
if len(stderr) > 0 {
log.Printf("%q: (stderr)\n%s", dir, stderr)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment