Golang 'exec.Command' treat single quote parameter special?

Issue

I am refer to the post How to execute system command with unknown arguments? to run a jq command on my ubuntu shell.
Below is the code I tried

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

func exeCmd(cmd string, wg *sync.WaitGroup) {
    fmt.Println("command is ",cmd)
    // splitting head => g++ parts => rest of the command
    parts := strings.Fields(cmd)
    head := parts[0]
    parts = parts[1:len(parts)]
  
    out, err := exec.Command(head,parts...).Output()
    if err != nil {
      fmt.Printf("%s", err)
    }
    fmt.Printf("%s", out)
    wg.Done() // Need to signal to waitgroup that this goroutine is done
  }

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(1)

    x := []string{"jq '(.data.legacyCollection.collectionsPage.stream.edges|map({node:(.node|{url,firstPublished,headline:{default:.headline.default},summary})})) as $edges|{data:{legacyCollection:{collectionsPage:{stream:{$edges}}}}}' long-response.json > short-response.json"}

    exeCmd(x[0], wg)

    wg.Wait()
}

The output is as below, seems like the commans is correctly detected but shell returns exit status 3 which is "no such process" ?

command is  jq '(.data.legacyCollection.collectionsPage.stream.edges|map({node:(.node|{url,firstPublished,headline:{default:.headline.default},summary})})) as $edges|{data:{legacyCollection:{collectionsPage:{stream:{$edges}}}}}' long-response.json > short-repsonse.json exit status 3

Anyone can help on this ?
What I want is a go function that can wrapper and run bash command line the same way as I do on Linux shell
PS: the jq command I tried above works pretty well when I paste it on my Linux shell

Tried somethine else: deleted the single quote in my jq command and my command got executed with output I expect – a parsed json file
but still, I got a exist status 2 , anyone can explain

  1. why the single quote in my command line affects how G parse the command ?
  2. why I still go exist 2 after my shell commands complete?

Solution

The program executes the jq command, not a shell. The jq command does not understand the shell syntax passed to the command (the quotes and I/O redirection).

Use the following code to run the command with stdout redirected to short-response.json.

cmd := exec.Command("jq",
    "(.data.legacyCollection.collectionsPage.stream.edges|map({node:(.node|{url,firstPublished,headline:{default:.headline.default},summary})})) as $edges|{data:{legacyCollection:{collectionsPage:{stream:{$edges}}}}}",
    "long-response.json")
f, err := os.Create("short-response.json")
if err != nil {
    log.Fatal(err)
}
defer f.Close()
cmd.Stdout = f  // set stdout to short-response.json
err = cmd.Run()
if err != nil {
    log.Fatal(err)
}

Answered By – Zombo

Answer Checked By – David Marino (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.