Search code examples
bashgosubprocessio-redirection

Capturing main process stdout into bash variable, keep printing subprocess output to console?


I'm developing a CLI. The CLI writes to stdout that I'd like to capture in a bash variable. That is, I'd like to be able to do this:

output=$(my_cli_command)

My CLI also runs a subprocess in that command. I'd like the output of the subprocess to be printed to the terminal when output=$(my_cli_command) is executed.

What do I have to do when running the subprocess to ensure that it (1) is printed to the console but (2) is not captured into the output variable? Or is this not possible?

I'm writing my CLI in Go. I've put a reproducible example here:

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    fmt.Println("I want this captured")

    // I don't want this captured, but I want "ls" printed to console
    command := exec.Command("ls")
    // With these lines, the print statement and the ls statement are printed to console.
    // All are captured in a bash variable.
    command.Stdout = os.Stdout
    command.Stderr = os.Stderr
    
    command.Run()

}

Copy that into a file main.go and run it like this:

output=$(go run main.go)
echo "$output"

Thank you.


Solution

  • This isn't a bash problem, it's a Go problem. If you don't want the output of ls to be captured, connect its stdout to your Go program's stderr rather than its stdout.

    package main
    
    import (
        "fmt"
        "os"
        "os/exec"
    )
    
    func main() {
        fmt.Println("I want this captured")
    
        command := exec.Command("ls")
        command.Stdout = os.Stderr // not os.Stdout
        command.Stderr = os.Stderr
        command.Run()
    }